1、sizeof的本质是运算符
sizeof
是C/C++中的关键字,是(单目)运算符或者操作符,而不是函数。用于判断变量或数据类型的字节大小,sizeof
运算符可用于获取类、结构、共用体和其他用户自定义数据类型的大小。
例如,
#includeint main(){ unsigned int a=4; if (a-8>0) printf("大于0");//有符号和无符号数运算,返回无符号数 if (sizeof(int)-8>0) printf("sizeof返回无符号整数"); else printf("小于0"); return 0;}
2、赋值运算符
“=”的左侧是变量,右侧是常量、变量、表达式、函数等,“=”的含义是将右边的值赋给左侧的变量,程序运行时先计算右侧值,然后赋给左侧变量。另外,还有复合赋值运算符,用法都基本相同,只是复合赋值运算符多了些其它操作。 C 语言支持的赋值运算符,如下表,
运算符 | 描述 | 实例 |
= | 简单的赋值运算符, 把右边操作数的值赋给左边操作数 | z = x + y 将把 x + y 的值赋给 z |
+= | 加且赋值运算符, 把右边操作数加上左边操作数的结果赋值给左边操作数 | z += x 相当于 z = z + x |
-= | 减且赋值运算符, 把左边操作数减去右边操作数的结果赋值给左边操作数 | z -= x 相当于 z = z - x |
*= | 乘且赋值运算符, 把右边操作数乘以左边操作数的结果赋值给左边操作数 | z *= x 相当于 z = z * x |
/= | 除且赋值运算符, 把左边操作数除以右边操作数的结果赋值给左边操作数 | z /= x 相当于 z = z / x |
%= | 求模且赋值运算符, 求两个操作数的模赋值给左边操作数 | z %= x 相当于 z = z % x |
<<= | 左移且赋值运算符 | z <<= 2 等同于 z = z << 2 |
>>= | 右移且赋值运算符 | z >>= 2 等同于 z = z >> 2 |
&= | 按位与且赋值运算符 | z &= 2 等同于 z = z & 2 |
^= | 按位异或且赋值运算符 | z ^= 2 等同于 z = z ^ 2 |
|= | 按位或且赋值运算符 | z |= 2 等同于 z = z | 2 |
隐式类型转换:编译系统是不能直接运算不同类型间的数据,必须转换为同类型方能运算。
例如,
#includeint main(){ int x = 21; int z ; z = x; printf("z = x,z 的值 = %d\n", z ); z += x; printf("z += x,z 的值 = %d\n", z ); z -= x; printf("z -= x,z 的值 = %d\n", z ); z *= x; printf("z *= x,z 的值 = %d\n", z ); z /= x; printf("z /= x,z 的值 = %d\n", z ); z = 200; z %= x; printf("z %= x,z 的值 = %d\n", z ); z <<= 2; printf("z <<= 2,z 的值 = %d\n", z ); z >>= 2; printf("z >>= 2,z 的值 = %d\n", z ); z &= 2; printf("z &= 2;,z 的值 = %d\n", z ); z ^= 2; printf("z ^= 2,z 的值 = %d\n", z ); z |= 2; printf("z |= 2,z 的值 = %d\n", z ); return 0; }
3、算术运算符
对计算机中数据进行算术运算的运算符,称为算术运算符,包括数学中学到的加减乘除和一些扩展。C 语言支持的算术运算符,如下表,
名称 | 符号 | 说明 |
加法运算符 | + | 双目运算符, 即应有两个量参与加法运算。 如a+b,4+8等。具有右结合性。 |
减法运算符 | - | 双目运算符。 但“-”也可作负值运算符, 此时为单目运算, 如-x,-5等具有左结合性。 |
乘法运算符 | * | 双目运算符,具有左结合性。 |
除法运算符 | / | 双目运算符,具有左结合性。 参与运算量均为整型时, 结果也为整型,舍去小数。 如果运算量中有一个是实型, 则结果为双精度实型。 |
求余运算符(模运算符) | % | 双目运算符,具有左结合性。 要求参与运算的量均为整型, 不能应用于float或double类型。 求余运算的结果等于两数相除后的余数, 整除时结果为0。 |
自增运算符 | ++ | 单目运算符,整数值增加 1 |
自减运算符 | -- | 单目运算符,整数值减少 1 |
例如,
#includeint main(){ int x = 21; int y = 10; int z ; z = x + y; printf("z = x + y 值是 %d\n", z ); z = x - y; printf("z = x - y 的值是 %d\n", z ); z = x * y; printf("z = x * y 的值是 %d\n", z ); z = x / y; printf("z = x / y 的值是 %d\n", z ); z = x % y; printf("z = x % y 的值是 %d\n", z ); z = x++; // 赋值后再加 1 ,z 为 21,x 为 22 printf("z = x++ 的值是 %d\n", z ); z = x--; // 赋值后再减 1 ,z 为 22 ,x 为 21 printf("z = x-- 的值是 %d\n", z );}
注意:
自增运算符,++i
:i自增1后再参与其它运算。--i
:i自减1后再参与其它运算。i++
:i参与运算后,i的值再自增1。i--
:i参与运算后,i的值再自减1
4、位运算符
位运算是指按二进制进行的运算。在系统软件中,常常需要处理二进制位的问题。C语言提供了6个位操作运算符。这些运算符只能用于整型操作数,即只能用于带符号或无符号的char
,short
,int
与long
类型。C 语言支持的位运算符,如下表,
运算符 | 描述 | 实例 |
& | 按位与操作, 按二进制位进行与运算。运算规则:
| (x & y) 将得到 12,即为 0000 1100 |
| | 按位或运算符, 按二进制位进行或运算。运算规则:
| (x | y) 将得到 61,即为 0011 1101 |
^ | 异或运算符, 按二进制位进行异或运算。运算规则:
| (x ^ y) 将得到 49,即为 0011 0001 |
~ | 取反运算符, 按二进制位进行取反运算。运算规则:
| (~x ) 将得到 -61,即为 1100 0011, 一个有符号二进制数的补码形式。 |
<< | 二进制左移运算符。 将一个运算对象的各二进制位全部左移若干位 (左边的二进制位丢弃,右边补0)。 | x << 2 将得到 240,即为 1111 0000 |
>> | 二进制右移运算符。 将一个数的各二进制位全部右移若干位, 正数左补0,负数左补1,右边丢弃。 | x >> 2 将得到 15,即为 0000 1111 |
例如,
#includeint main(){ unsigned int x = 60; /* 60 = 0011 1100 */ unsigned int y = 13; /* 13 = 0000 1101 */ int z = 0; z = x & y; /* 12 = 0000 1100 */ printf("z = x & y 的值是 %d\n", z ); z = x | y; /* 61 = 0011 1101 */ printf("z = x | y 的值是 %d\n", z ); z = x ^ y; /* 49 = 0011 0001 */ printf("z = x ^ y 的值是 %d\n", z ); z = ~x; /*-61 = 1100 0011 */ printf("z = ~x 的值是 %d\n", z ); z = x << 2; /* 240 = 1111 0000 */ printf("z = x << 2 的值是 %d\n", z ); z = x >> 2; /* 15 = 0000 1111 */ printf("z = x >> 2 的值是 %d\n", z );}
5、逻辑运算符
逻辑运算符用来表示日常交流中的“并且”,“或者”,“除非”等思想。逻辑运算符很重要的法则是短路法则。即,(表达式1)&&(表达式2) 如果表达式1为假,则表达式2不会进行运算,即表达式2“被短路”,(表达式1)||(表达式2) 如果表达式1为真,则表达式2不会进行运算,即表达式2“被短路”。逻辑运算符的运算顺序都是从左到右计算。C 语言支持的逻辑运算符,如下表,
运算符 | 描述 | 实例 |
&& | 称为逻辑与运算符。 如果两个操作数都非零, 则条件为真。 | (x && y) 为假。 |
|| | 称为逻辑或运算符。 如果两个操作数中有任意一个非零, 则条件为真。 | (x || y) 为真。 |
! | 称为逻辑非运算符。 用来逆转操作数的逻辑状态。 如果条件为真则逻辑非运算符将使其为假。 | !(x && y) 为真。 |
例如,
#includeint main(){ int x = 5; int y = 20; if ( x && y ) { printf("x && y - 条件为真\n" ); } if ( x || y ) { printf("x || y - 条件为真\n" ); } /* 改变 x 和 y 的值 */ x = 0; y = 10; if ( x && y ) { printf("x && y - 条件为真\n" ); } else { printf("x && y - 条件为假\n" ); } if ( !(x && y) ) { printf("x && y - 条件为真\n" ); }}
6、三目运算符(三元运算符)
三目运算符,又称条件运算符,是计算机语言(c,c++,java等)的重要组成部分。它是唯一有3个操作数的运算符,所以有时又称为三元运算符。一般来说,三目运算符的结合性是右结合的。三目运算符语法如下,
condition ? value_if_true : value_if_false
上面表达式是先计算条件condition,然后进行判断。如果condition的值为true
,计算value_if_true的值,运算结果为value_if_true的值;否则,计算value_if_false的值,运算结果为value_if_false的值。一个条件表达式绝不会既计算value_if_true,又计算 value_if_false。条件运算符是右结合的,也就是说,从右向左分组计算。
例如,
#includeint main(){ int x = 4; short y; /* 三元运算符实例 */ x = 10; y = (x == 1) ? 20: 30; printf( "y 的值是 %d\n", y ); y = (x == 10) ? 20: 30; printf( "y 的值是 %d\n", y );}
7、指针运算符(* 和 &)
&
运算符只能用于内存中的对象,即变量与树组元素,它不能作用于表达式、常量或register类型的变量。*
运算符用于指针时表示访问指针所指向的对象。
1)&运算符
&a //表示变量a的存放地址b = &a //表示把变量a的地址赋值给变量b
2)*运算符
a = 3; //将a复制为3 c = &a; //把a的地址赋值给cd = *c; //取出c存放a地址中的值,并赋值给dprintf("d = %d",d); //打印d
8、运算符优先级
运算符的优先级确定表达式中项的组合。这会影响到一个表达式如何计算。某些运算符比其他运算符有更高的优先级,例如,乘除运算符具有比加减运算符更高的优先级。C 语言支持的运算符优先级,如下表,
优先级 | 运算符 | 名称或含义 | 使用形式 | 结合方向 | 说明 |
1 | [] | 数组下标 | 数组名[常量表达式] | 左到右 | -- |
() | 圆括号 | (表达式)/函数名(形参表) | -- | ||
. | 成员选择(对象) | 对象.成员名 | -- | ||
-> | 成员选择(指针) | 对象指针->成员名 | -- | ||
2 | - | 负号运算符 | -表达式 | 右到左 | 单目运算符 |
~ | 按位取反运算符 | ~表达式 | |||
++ | 自增运算符 | ++变量名/变量名++ | |||
-- | 自减运算符 | --变量名/变量名-- | |||
* | 取值运算符 | *指针变量 | |||
& | 取地址运算符 | &变量名 | |||
! | 逻辑非运算符 | !表达式 | |||
(类型) | 强制类型转换 | (数据类型)表达式 | -- | ||
sizeof | 长度运算符 | sizeof(表达式) | -- | ||
3 | / | 除 | 表达式/表达式 | 左到右 | 双目运算符 |
* | 乘 | 表达式*表达式 | |||
% | 余数(取模) | 整型表达式%整型表达式 | |||
4 | + | 加 | 表达式+表达式 | 左到右 | 双目运算符 |
- | 减 | 表达式-表达式 | |||
5 | << | 左移 | 变量<<表达式 | 左到右 | 双目运算符 |
>> | 右移 | 变量>>表达式 | |||
6 | > | 大于 | 表达式>表达式 | 左到右 | 双目运算符 |
>= | 大于等于 | 表达式>=表达式 | |||
< | 小于 | 表达式<表达式 | |||
<= | 小于等于 | 表达式<=表达式 | |||
7 | == | 等于 | 表达式==表达式 | 左到右 | 双目运算符 |
!= | 不等于 | 表达式!= 表达式 | |||
8 | & | 按位与 | 表达式&表达式 | 左到右 | 双目运算符 |
9 | ^ | 按位异或 | 表达式^表达式 | 左到右 | 双目运算符 |
10 | | | 按位或 | 表达式|表达式 | 左到右 | 双目运算符 |
11 | && | 逻辑与 | 表达式&&表达式 | 左到右 | 双目运算符 |
12 | || | 逻辑或 | 表达式||表达式 | 左到右 | 双目运算符 |
13 | ?: | 条件运算符 | 表达式1? 表达式2: 表达式3 | 右到左 | 三目运算符 |
14 | = | 赋值运算符 | 变量=表达式 | 右到左 | -- |
/= | 除后赋值 | 变量/=表达式 | -- | ||
*= | 乘后赋值 | 变量*=表达式 | -- | ||
%= | 取模后赋值 | 变量%=表达式 | -- | ||
+= | 加后赋值 | 变量+=表达式 | -- | ||
-= | 减后赋值 | 变量-=表达式 | -- | ||
<<= | 左移后赋值 | 变量<<=表达式 | -- | ||
>>= | 右移后赋值 | 变量>>=表达式 | -- | ||
&= | 按位与后赋值 | 变量&=表达式 | -- | ||
^= | 按位异或后赋值 | 变量^=表达式 | -- | ||
|= | 按位或后赋值 | 变量|=表达式 | -- | ||
15 | , | 逗号运算符 | 表达式,表达式,… | 左到右 | -- |
例如,
#includeint main(){ int x = 40; int y = 20; int z = 30; int d = 10; int s; s = (x + y) * z / d; printf("(x + y) * z / d 的值是 %d\n", s ); s = ((x + y) * z) / d; printf("((x + y) * z) / d 的值是 %d\n" , s ); s = (x + y) * (z / d); printf("(x + y) * (z / d) 的值是 %d\n", s ); s = x + (y * z) / d; printf("x + (y * z) / d 的值是 %d\n" , s ); return 0;}