美文网首页
类型、运算符与表达式

类型、运算符与表达式

作者: 漫游之光 | 来源:发表于2018-09-12 16:54 被阅读0次

变量和常量是程序处理的两种基本数据对象。声明语句说明变量的名字及类型,也可以指定变量的初值。运算符指定将要进行的操作。表达式则把变量与常量组合起来生成新的值。对象的类型决定该对象可取的集合以及可以对该对象执行的操作。

变量名

名字是由字母和数字组成的序列,但其第一个字符必须为字母。下划线“_”被看做是字母,但不能以下划线开头。

数据类型及长度

类型 说明
char 字符型 占用一个字节,可以存放本地字符集中的一个字符
int 整型 通常反映了所用机器中整数的最自然长度
short和long两个限定符用于限定整数,可省略int
float 单精度浮点型
double 双精度浮点型

signed和unsigned用于限定char类型或任何整型。signed代表有符号数,unsigned代表无符号数。

例子:打印signed和unsigned限定的long类型变量的取值范围。

#include<stdio.h>

int main(int argc, char const *argv[])
{
    printf("signed long max = %ld\n",(long)(((unsigned long)~0)>>1));
    printf("signed long min = %ld\n",(long)((((unsigned long)~0)>>1)+1));
    printf("unsigned long max = %lu\n",(long)~0);
    printf("unsigned long max = %lu\n",0);
    getchar();
    return 0;
}

其实这里涉及数据在计算机中的表示,无符号数比较好表示最大全1,最小全0。但对于有符号的,由于整型常量默认为int,先得到全1,然后符号扩展。在C语言中,将int强转为unsigned long执行的操作是,先将int进行扩展,然后在把有符号转化为无符号,符号转化并不改变数据,只是改变了看待数据的方式。所以这里就得到全1,然后对无符号数执行逻辑右移,得到了0后面全1这个序列,也就是我们想得到的long的最大数。对于最小数,即1后面全0,只需要把0后面全1的序列加1即可,然后在进行强转,就可以打印出来了。不转也可以,因为printf中的%ld相当于就执行了类型转换。

常量

类型 说明
int类型常量 类似于1234的整数常量
long类型常量 以l或L结尾的整数常量,或整数太大int类型无法表示
double类型常量 常量整数中有小数点或一个指数
float类型常量 常量整数中有小数点或一个指数且后缀为f或F
long double类型常量 常量整数中有小数点或一个指数且后缀为l或L
字符常量 '字符',代表字符,在计算机中存储为整数,'\0',代表空字符,有些字符需要转义
字符串常量 用双引号括起来的0个或多个字符组成的字符序列
字符串内部使用一个空字符‘\0’作为字符串结尾
枚举常量 一个常量整型值列表,默认第一个枚举名为0,第二个为1,依次类推
可以指定枚举值,如果只指定了部分枚举值,未指定的依次往后递增
常量表达式 仅仅包含常量的表达式,在编译时求值,而不在运行时求值

枚举值的示例如下:

#include<stdio.h>

enum letter{
    CHAR_O,CHAR_A = 'A',CHAR_B
};

int main(int argc, char const *argv[])
{
    /* 结果为CHAR_O = 0,CHAR_A = A,CHAR_B = B */
    printf("CHAR_O = %d,CHAR_A = %c,CHAR_B = %c\n",CHAR_O,CHAR_A,CHAR_B);
    return 0;
}

声明

所有变量都必须先声明后使用,一个声明指定一种变量类型,后面所带的变量表可以包含一个或多个该类型的变量,并且可以在声明的同时对变量进行初始化。任何声明变量的声明都可以使用const声明,该限定符指定变量的值不能被修改。const限定符也可以配合数组或指针函数参数使用,表明函数不能修改指针指向的值(数组也可以看做是指针)。

void fun(const char *s){
    *s = 'A';/* 错误,不能修改指向的值 */
}

int main(int argc, char const *argv[])
{
    char c = 'A';
    /* const修饰*p1 */
    const char *p1= &c;/* 等价于 char const *p1 = &c; */
    /* const修饰p2 */
    char* const p2 = &c;
    (*p1)++;/* 错误,不能修改指向的内容 */
    (*p2)++;
    p1 = NULL;
    p2 = NULL;/* 错误,不能修改指针本身的值 */
    getchar();
    return 0;
}

算术运算符

二元算术运算符包括:+、-、*、/、%(取模运算符)。整数除法会截断结果中的小数部分。表达式x % y的结果是x除以y的余数,当x能被y整除时,其值为0。

关系运算符与逻辑运算符

关系运算符包括下列几个运算符:<,>=,<,<=,他们具有相同的优先级,优先级仅次于它们的是相等性运算符==,!=。
逻辑运算符有&&,||,!。&&两个都为真时为1,否则为0,||两个都为假是为0,否则为1。!的作用是将非0操作数转换为0,将操作数0转换为1。有&&与||连接的表达式按从左往右的顺序进行求值,而且,再知道结果值为真或假后立即停止计算。

类型转换

自动转换:指把“比较窄的”操作数转换为“比较宽的”操作数,并且不会发生信息的丢失。如把int转化为long。
强制类型转换,格式如下:

    (类型名)表达式

我们可以这样理解强制类型转换的准确含义:在上述语句中,表达式首先被赋值给类型名指定的某个变量,然后再用变量替换上述整条语句。
例子:

static unsigned long int next = 1;

/* 返回一个随机数 */
int b_rand(void){
    next = next * 1103515245 + 12345;
    return (unsigned int)(next/65535) % 32768;
}
/* 设置随机数的种子 */
void b_srand(unsigned int seed){
    next = seed;
}

/* 将一个数字字符串转化为int型数 */
int b_atoi(char s[]){
    int n=0;
    int i;
    for(i=0;s[i]!='\0';i++){
        if('0'<=s[i]&&s[i]<='9'){
            n = n*10 + s[i] - '0';
        }
    }
    return n;
}

自增自减运算符

自增运算符++使其操作数递增1,自减运算符--使其操作数递减1。++与--这两个运算符特殊的地方主要表现在,它们即可以作前缀运算符,也可以作后缀运算符。在这两种情况下,其效果都是将变量n值加1。但是,它们之间有一点不同。表达式++n先将n的值递增1,然后再使用变量n的值,而表达式n++则是先使用变量n的值,然后在将n的值递增1。也就是说,对于使用变量n的值得上下文来说,++n和n++的效果是不同的。如果n的值为5,那么

    x = n++;

x的值为5,而

    x = ++n;

x的值为6。
例子:

void b_squeeze(char s[],int c){
    int i=0;
    int j=0;
    for(i=0;s[i] != '\0';i++){
        if(s[i] != c){
            s[j++] = s[i];
        }
    }
    s[j] = '\0';
}

这个程序示比较简单的,但是我犯了一个错误,我调用的时候,使用了以下方式调用:

    char *s = "cshasscstedstge";
    b_squeeze(s,'s');

这个错误在于,字符串常量是存储在只读存储区的,这种方式调用会导致对只读存储区的写操作,会触发一个段错误。

按位运算符

符号 名称 运算规则(每一位之间)
& 两个都为1,则为1,否则为0
| 两个都为0,则为0,否则为1
~ 0变为1,1变为0
^ 异或 两个相异为1,相同为0
<< 左移 将数据的n比特左移,在右边补0
>> 右移 逻辑右移:将数据向右移动n比特,左边补0
算数右移:将数据向右移动n比特,左边补最高位

例子:

/* 得到从p位开始的n位 */
unsigned int getbits(unsigned int x,int p,int n){
    return (x>>(p-n+1)) & (~(~0<<n));
}

赋值运算符与表达式

在赋值表达式中,如果表达式左边的变量重复出现在表达式的右边,如:

    i = i+ 2

则可以将这种表达式缩写为下列形式:

    i += 2

其中+=称为赋值运算符。
大多数的二元运算符,都有一个相应的赋值运算符op=,其中,op可以是下列运算符之一:+,-,*,/,%,<<,>>,&,^,|。如果expr1和expr2是表达式,那么

    expr1 op= expr2

等价于:

    expr1 = (expr1)op(expr2)

例子:

/* 记录x中有多少位为1 */
int bitcount(unsigned int x){
    int n;
    for(n = 0;x!=0;x &= x-1){
        n++;
    } 
    return n;
}

条件表达式

在表达式

    expr1 ? expr2 : expr3

中,首先计算expr1,如果其值不等于0,则计算expr2的值,并以该值作为条件表达式的值,否则计算expr3的值,并以该值作为条件表达式的值。expr2与expr3中只能有一个表达式被计算。

运算符优先级

运算符 结合性
() [] -> . 从左至右
! ~ ++ -- + - & (type) sizeof 从右至左
* / % 从左至右
+ - 从左至右
<< >> 从左至右
< <= > >= 从左至右
== != 从左至右
& 从左至右
^ 从左至右
| 从左至右
&& 从左至右
|| 从左至右
?: 从右至左
= += -= *= /= %= &= 从右至左
^= |= <<= >>= 从左至右
, 从左至右

相关文章

  • JULIA-类型

    类型操作 断言运算符::::,作为运算符时语法:左表达式::右数据类型,判断“左表达式”是否为“右数据类型”的实例...

  • Java基础恢复(待完善)

    1. 环境配置(MAC) 2. 基础 标识符 常量与变量 常量 变量 运算符和表达式 运算符 表达式 数据类型 4...

  • 2020年3月11日 第二章 基本数据类型、运算符和表达式 -1

    第二章 基本数据类型、运算符和表达式 -1 1.基本数据类型 2.运算符 3.常用内置函数 4.表达式、赋值语句与...

  • Day03_运算符_键盘录入

    运算符 关系运算符 逻辑运算符 是用来连接布尔表达式的, 结果也为boolean类型. & 逻辑与,表示并且.有f...

  • MySQL 中的运算符(一)

    MySQL 支持多种类型的运算符,来连接表达式的项。这些类型主要包括算术运算符、比较运算符、逻辑运算符和位运算符。...

  • 学习计算机之路(C语5 运算符和表达式)

    1.0运算符与表达式 现在为止,C语言中的各种基本数据类型的特点和形式我们都已经了解了! 运算符和表达式是用来进行...

  • PHP|类型转换 ,常量,系统常量,魔术常量

    1.自动类型转换;## 2、强制类型转化 3、常量 4.运算符和表达式;1)算数运算符 + - *(乘法) /(...

  • python的运算符与表达式

    运算符与表达式 1.关系运算符 关系运算符:​ == != > < >= <=关系运算表达式:​ 格...

  • 第三天

    比较运算符,运算完的结果必须是true或者false 逻辑运算符用于连接两个boolean类型的表达式 &:与 |...

  • C语言6 运算符和表达式

    C语言6 运算符和表达式 运算符与表达式 什么是运算符?什么是表达式? 表达式的结果 表达式不论怎么复杂。最终只有...

网友评论

      本文标题:类型、运算符与表达式

      本文链接:https://www.haomeiwen.com/subject/ylxbgftx.html