运算符和表达式¶
约 895 个字 51 行代码 3 张图片 预计阅读时间 4 分钟
牢记几句话
表达式的值
表达式定义:
运算符 + 运算对象
运算对象:常量、变量和函数等表达式
分类
算术表达式、赋值表达式、关系表达式、逻辑表达式、条件表达式和逗号表达式
优先级¶
最好都加上括号
-
逻辑表达式:C赋值:真1 假0
-
循环判断:非零真
-
++ --
- 数据的值一样,表达式的值不一样
- a++:表达式:a+1之前的值,把表达式的值赋给其他
- ++a:表达式:a+1之后的值,把表达式的值赋给其他
- 数据的值一样,表达式的值不一样
-
只能对变量不能对表达式用
-
左右结合:先从哪边算
-
x = y = 3 : 不能在变量定义处用,可以后面用,结合顺序
-
复合赋值:i+=1:更高效
-
逻辑运算短路:
- ||:前面真后面不算
- &&:前面假后面不算
-
逗号运算符:值是最后一个子表达式的值
位运算¶
结果是表达式的值
重点
计算机中,数字的储存、运算都是以 补码 形式
Ctrl F 数字编码
位逻辑运算¶
~按位取反
& 按位与
特点: 全1才1
应用:
-
让某一位或者某些位为0
示例:
x & 0xFE:将最后一位变成0 -
取一个数中的一段
示例:
x & 0xFF:取出最后两个字节中的内容
| 按位或
特点: 有1则1
应用:
-
将某些位变为1:或上那一位为1的数
示例:
x | 0x01最右边一位为1 -
将两个数拼起来
示例:
0x00FF | 0xFF00
逻辑运算(&&、||)相当于将所有非0值都变成1,然后做按位对应运算
^ 按位异或
特点 :
- 两个位相同得0,不同得1
x ^ y ^ y 变回到 x
移位运算¶
箭头朝向即为移动方向
移动的位数为正
i << j 对x的所有位左移j个位置,右边填入0
-
x <<= n大多数情况下等价于x *= $2^n$-
当左移的位数超过位宽(
sizeof(int) * 8)或有符号数符号位变化时,将导致未定义行为 -
位移导致舍弃前面的位的情况也不是
-
i >> j 对x的所有位右移j个位置
- 对于unsigned类型,左边填0
- 对于signed类型,符号位保持不变,原来的高位移到地位
x >>= n大多数情况下等价于x /= $2^n$
直接遗弃超出范围的位
复合位赋值运算¶
&=,|=,^=,>>=,<<=
a &= b 等价于 a = a & b; a >>= 3 等价于 a = a >> 3
应用¶
-
伪转换二进制
-
单片机
位段¶
语法:
- 可以直接用位段的成员名访问
注意事项:
-
存储大小与对齐:
位段的存储大小通常以 int 或 unsigned int 为单位,且会受编译器的内存对齐策略影响。
多个位段成员可能共享同一个存储单元(如果其总位宽小于存储单元大小),但如果超出单元大小,会分配下一个单元。
-
即,所需的位超过一个int时会采用多个int
-
因此,访问位段成员的地址的操作是有语法错误的
-
-
数据类型的限制:
位段成员通常只能是 int 或 unsigned int,具体限制依赖于编译器。
-
移植性问题:
不同编译器和平台对位段的实现(如存储顺序、对齐方式)可能不同,可移植性较差。
-
位宽限制:
位宽不能超过存储单位的大小。例如,如果 int 是 32 位,位宽不能大于 32。
示例:
struct U0 {
unsigned int leading: 3;
unsigned int FLAG1: 1;
unsigned int FLAG2: 1;
int trailing: 27;
};
void toBinary(int num)
{
unsigned int mask = 1u << 31;
for(; mask; mask >>= 1){
printf("%d", num & mask ? 1 : 0);
}
}
int main()
{
struct U0 num1, num2;
num2.leading = 2;
num2.FLAG1 = 1;
num2.FLAG2 =0;
num2.trailing = 0;
printf("please enter your number_1: ");
scanf("%x", &*(int*)&num1);
printf("the binary of your number_1 is: ");
toBinary(*(int*)&num1);
printf("\n");
printf("the binary of your number_1 is: ");
toBinary(*(int*)&num2);
printf("\n");
return 0;
}
应用场景: 底层,对硬件的操作
-
嵌入式开发:
在嵌入式系统中,用位段模拟硬件寄存器的各个位字段。 - 网络协议:
用位段解析网络协议的标志字段(如 TCP/IP 报头)。 - 标志集合:
用位段压缩存储多个布尔标志,以节省内存。


