本文已参与「新人创作礼」活动,一起开启掘金创作之路。
C语言运算符从逻辑数个数上看,可分为一目、二目、三目运算符。
一、算术运算符
| 运算符 | 作用 | 示例 | 结果 |
|---|---|---|---|
| + | 对左右两个操作数进行加法运算 | 7+4 | 11 |
| - | 对左右两个操作数进行减法运算 | 7-4 | 3 |
| * | 对左右两个操作数进行乘法运算 | 7*4 | 28 |
| / | 对左右两个操作数进行除法运算 | 7/4 | 1 |
| % | 对左右两个操作数进行取模(求余)运算 | 7%4 | 3 |
这五个算术运算符都是二目运算符,算术运算符的作用是为了求值。 乘法、除法、取模运算符的优先级要比加法、减法的优先级高。
1.隐式转换
在进行算术运算时,在左右两个操作数中,将以最大的那个数据类型为标准进行运算,也就是会先把较小的那个数据类型转换成较大的数据类型,然后再进行运算。把小类型自动转化为大类型的过程,我们把它称为“隐式类型转换”。 下面简单列举一些常用的:
char < int < float < double 7 / 4 = 1 7.0 / 4 = 1.75 7 / 4.0 = 1.75
2.除法运算中,除数不能为0
如果除数为0,就会得到错误的结果。
3.取模运算时两边的操作数都应是整型
取模运算时两边的操作数都应是整型,并且只有左边操作数才会影响到结果的正负关系,即左操作数若为正,则取模结果也为正值。反之,若左操作数为负值取模结果也为负值。
7 % -4 = 3 -7 % 4 = -3
二、关系运算符
| 运算符 | 作用 | 示例 | 结果 |
|---|---|---|---|
| == | 比较左右两个操作数是否相等 | 5 == 8 | 0 |
| != | 比较左右两个操作数是否不相等 | 5 != 8 | 1 |
| < | 比较左操作数是否小于右操作数 | 5 < 8 | 1 |
| <= | 比较左操作数是否小于或等于右操作数 | 5 <= 8 | 1 |
| 比较左操作数是否大于右操作数 | 5 > 8 | 0 | |
| >= | 比较左操作数是否大于或等于右操作数 | 5 >= 8 | 0 |
上面的关系运算符都是二目运算符,为了比较左右两个操作数的大小关系。 C语言用1来表示真,用0来表示假。但能表示真的值不仅仅只是1,而是任何的非零值。只不过通常都用1来表示真。
三、逻辑运算符
| 运算符 | 类型 | 作用 | 示例 | 结果 |
|---|---|---|---|---|
| ! | 单目 | 得到一个反转操作数的逻辑值 | ! 0(! 1) | 1(0) |
| && | 双目 | 当左右两边的逻辑值都为真时,结果为真,其它情况全为假 | 1&&1 (0&&1、1&&0、0&&0) | 1(0) |
| || | 双目 | 当左右两边的逻辑值都为假时,结果为假,其它情况结果全为真 | 0||1、1||0、1||1 (0||0) | 1(0) |
1.短路效果
当使用逻辑与运算符时,若左操作数的结果为假,则直接返回结果为假,而不是去检查右操作数。 使用逻辑或运算符时,若左操作数的结果为真,则直接返回结果为真,也不会再去检查右操作数。
四、位运算符
| 运算符 | 名称 | 作用 | 类型 |
|---|---|---|---|
| << | 按位左移运算符 | 将所有的位向左(高位)移动,低位补0 | 双目 |
| >> | 按位右移运算符 | 将所有的位向右(低位)移动,高位对于无符号类型强制补0,对于有符号类型续补符号位 | 双目 |
| ~ | 按位取反运算符 | 将所有位反转(1变为0,0变为1) | 单目 |
| & | 按位与运算符 | 将两操作数按位进行与操作 | 双目 |
| | | 按位或运算符 | 将两操作数按位进行或操作 | 双目 |
| 按位异或运算符 | 将两操作数按位进行异或的操作 | 双目 |
逻辑运算符都是对操作数进行运算的,而位运算符是对操作数的二进制位进行运算的。 下面对整数23,其8位二进制码为0001 0111
23<<1 得0010 1110
23>>1 得0000 1011
~23 得1110 1000
23&50 得0001 0010
23|50 得0011 0111
23^50 得0010 0101 (异或:两位不同时,一位为1,一位为0,结果为1)
五、复合赋值运算符
| 运算符 | 作用 | 示例 | 相当于 |
|---|---|---|---|
| += | 将左边变量值与右操作数相加后再赋值给左边变量 | a += 1 | a = a + 1 |
| -= | 将左边变量值与右操作数相减后再赋值给左边变量 | a -= 1 | a = a - 1 |
| *= | 将左边变量值与右操作数相乘后再赋值给左边变量 | a *= 1 | a = a * 1 |
| /= | 将左边变量值与右操作数相除后再赋值给左边变量 | a /= 1 | a = a / 1 |
| %= | 将左边变量值与右操作数取模后再赋值给左边变量 | a %= 1 | a = a % 1 |
| <<= | 将左边变量值按位左移右操作数指定位后再赋值给左边变量 | a <<= 1 | a = a << 1 |
| >>= | 将左边变量值按位右移右操作数指定位后再赋值给左边变量 | a >>= 1 | a = a >> 1 |
| &= | 将左边变量值与右操作数进行按位与后再赋值给左边变量 | a &= 1 | a = a & 1 |
| |= | 将左边变量值与右操作数进行按位或后再赋值给左边变量 | a |= 1 | a = a | 1 |
| ^= | 将左边变量值与右操作数进行按位异或后再赋值给左边变量 | a ^= 1 | a = a ^ 1 |
这些运算符只能对可修改的变量使用,不可用于常量。
六、带副作用的运算符
赋值运算符、复合赋值运算符、自增、自减运算符。 我们通常把这些能够改变操作数的行为称为“副作用”,把拥有这类行为的运算符称为“带副作用的运算符”。
七、自增、自减运算符
是一目运算符,也是带副作用的运算符。 a的初值为1
| 运算符 | 形式 | 作用 | 示例 | 结果 |
|---|---|---|---|---|
| ++ | 前缀自增 | 将操作数加1并返回操作数的新值 | ++a | 2 |
| ++ | 后缀自增 | 将操作数加1并返回操作数的原值 | a++ | 1 |
| - - | 前缀自减 | 将操作数减1并返回操作数的新值 | - -a | 0 |
| - - | 后缀自减 | 将操作数减1并返回操作数的原值 | a- - | 1 |
如果我们只是单纯地希望操作数加1,而不会去使用这个新值,则不管使用前缀的或者后缀的自增运算符都可以;反之如果需要使用这个新值,则前缀的与后缀的就有区别了。
八、其它运算符
1.类型转换运算符()
自动将小类型转换为大类型的行为就属于隐式类型转换。 现在讲的这个显式类型转换,它不但可以像隐式类型转换一样将一个小类型转换为大类型,而且也可以将一个大类型转换为一个小类型,这是隐式类型转换做不了的。
(数据类型) 操作数 小括号内的数据类型表示要转换的目的数据类型。
2.逗号运算符
int a; a =(3,4,5); 结果为5
int a; a = 3,4,5; 结果为3
3.条件运算符
是一个三目运算符
操作数1 ? 操作数2 : 操作数3 如果操作数1为真,则返回操作数2,反之返回操作数3。
4.sizeof运算符
sizeof (操作数); 这个操作数可以是一种数据类型,也可以是某种数据类型的常量或变量。 若操作数是一种数据类型,那么必须使用小括号,如果操作数并非是数据类型的话,就可以省略小括号。
sizeof运算符就可以返回它的大小,以字节为单位。通过sizeof运算符就可以很方便地获知某种数据类型在内存中所占用的空间大小。