之前为了说明变量的存储方式和运算过程,将 (!~)单独举例进行了说明,这里再对其他的一些操作符作一些补充。不变的原则是,C语言中
整数
的运算以变量补码的方式进行。
1.操作符的优先级
1.1 优先级列表
下标列出了C 运算符的优先级和结合性。运算符优先等级按降序从上到下列出。
优先级 | 操作符 | 描述 | 结合性 |
---|---|---|---|
1 | ++ -- | Suffix/postfix(后缀)递增和递减 | 左到右 |
() | 函数调用 | ||
[] | 数组下标 | ||
. | 结构和联合成员访问 | ||
-> | 通过指针访问结构体和联合体成员 | ||
(type){list} | 复合字面量(C99) | ||
2 | ++ -- | 前缀递增和递减 | 右到左 |
+ - | 一元加减 | ||
! ~ | 逻辑非和按位取反 | ||
(type) | 类型转换 | ||
* | 解引用 | ||
& | 取地址 | ||
sizeof | 变量的尺寸 | ||
_Alignof | 对齐要求(C11) | ||
3 | * / % | 乘法、除法和余数 | 左到右 |
4 | + - | 加减 | |
5 | << >> | 按位左移和右移 | |
6 | < <= | 关系运算符 < 和 ≤ | |
> >= | 关系运算符 > 和 ≥ | ||
7 | == != | 关系运算符 = 和 ≠ | |
8 | & | 按位与 | |
9 | ^ | 按位异或(异或) | |
10 | | | 按位或 | |
11 | && | 逻辑与 | |
12 | || | 逻辑或 | |
13 | ?: | 三元条件 | 右到左 |
14 | = | 简单赋值 | |
+= -= | 按和、差赋值 | ||
*= /= %= | 按乘积、商和余数赋值 | ||
<<= >>= | 按位左移和按位右移赋值 | ||
&= ^= |= | 按位 与、异或 和 或 赋值 | ||
15 | , | 逗号 | 左到右 |
1.2 注释
-
前缀的++和-- 不能作用于强制类型转换的操作数。
-
表达式sizeof (int) * p被解释为(sizeof(int)) * p,而不是sizeof((int)*p)
-
在三元条件
?:
内添加表达式,表达式默认添加了括号。 -
对于结合性的理解:a = b = c, 表格内说从右向左,即 a = ( b = c ),右边的赋值先执行。
另外:C语言标准没有指定优先级,他们来自语法。还要注意不要写过于复杂的表达式,不要给人挖坑也不要为难自己。
2 操作符举例
2.1 / 和%
/
表示 除法,可以用于整数和浮点数运算,当表示整数除法时,结果等于被整除的部分;而%
表示取余操作,只能
用于整数的运算。
2.2 >>和<<
>>
表示二进制补码按位右移,<<
表示二进制补码按位左移。实现这个部分的单元被称为移位寄存器,如下:
移位运算有循环移位(高位移出补到低位;低位移出补到高位)、逻辑移位(移出的位丢弃,空缺位补0)、算数移位(移除位丢弃,空缺位用符号位填充),具体实现什么样的移位过程,由计算机的控制指令决定,而具体给什么指令,则由编译器编译决定,只要C语言没给出标准,编译器可以自行决定控制器的指令。
在VS2015中:
-
对于无符号数(unsigned),只执行
逻辑移位
。 -
对于有符号数(signed):
- 左移:逻辑移位
- 右移:算数移位
2.3 ^
关于异或操作符^
,表示两个二进制数对应位,相异为1,相同为0
。
这里再对二进制位的运算做一个复习。
另外对于^
使用有个小技巧:用于整型变量的交换
2.4 sizeof
sizeof用来计算内存空间的大小(单位byte
),它属于
操作符,不是函数。另外要注意的是,sizeof中的表达式不参与计算
,原因是在预编译时,sizeof()
整个就被替换成了4
(如下),a++
后面不再出现了。
2.5 && 和 ||
逻辑与
和逻辑或
,他们的运算结果只表示真假。有关它们的一个细节是,当赋值操作多变量时,对于&&
只要有假
往后都不执行了;对于||
只要有真
往后都不执行了。