文章目录
- C语言笔记8:操作符
-
- 一、进制转换
- 二、原码、反码、补码
- 三、移位操作符
- [四、位操作符 &、|、^、~](#四、位操作符 &、|、^、~)
-
- [不创建临时变量,交换a 、b变量的值](#不创建临时变量,交换a 、b变量的值)
- 求整数存储在内存(补码)的二进制数中,1的个数
- 将数字的某个二进制位置0或置1
- 五、逗号表达式
- 六、操作符的优先级和结合性
- 七、整型提升
- 八、算术转换
- 九、问题表达式
C语言笔记8:操作符
一、进制转换
十进制转二进制
125.25转二进制
125:除2取余
0.25:乘2取整所以125.25转为二进制应该是:1111101.01
二进制和十六进制和八进制互相转换
C语言中表示八进制是在开头带0,表示十六进制是开头带0x,但这只是C语言的规定。比如汇编中表示十六进制则是0或0x开头,h结尾。
cint main() { int n = 15; int m = 014; int x = 0x6F; return 0; }m,x转二进制:
二、原码、反码、补码
正整数的原码反码补码都相同
负整数:
原码:符号位为1其余不变
反码:符号位不变,其余位按位取反
补码:反码+1
对于整型数据,内存中存放的都是补码
为什么要用补码呢?
这是为了适配硬件和提高效率,有了补码之后,减法可以用加法代替。并且负整数的原码和补码的相互转换是同样的过程。
三、移位操作符
算术右移和逻辑右移:
C语言的右移分逻辑右移和算术右移,也就是操作数是有符号的数字时,进行算术右移,操作数是无符号数字时进行的是,逻辑右移
这导致一个结果,C语言右移的值总是等于向下取整的除以2^n的运算。
cint main() { char a = -1;//验证逻辑右移和算术右移 补码:10000001 11111110 11111111 unsigned char b = 255;//补码:11111111 a >>= 1;//11111111:FF b >>= 1;//01111111:7F //a = -1 a/2并向下取整 = -0.5 -> -1 //b = 255 b/2并向下取整 = 127.5 -> 127 return 0; }这和除法的规则是不一样的,C语言除法是向0取整而不是单纯的向下取整。

逻辑左移:
C语言的左移则是统统逻辑左移:这导致C语言的左移只要没有发生溢出,左移的结果就是乘以2^n。
注意事项
移位操作符不要移动负数位
比如a >>
-1;这种写法是未定义的
四、位操作符 &、|、^、~
通过题目来熟悉这些操作符吧
不创建临时变量,交换a 、b变量的值
c
int main()
{
int a = 10;
int b = 20;
a = a ^ b;
b = a ^ b;
a = a ^ b;
return 0;
}
求整数存储在内存(补码)的二进制数中,1的个数
c
int main()
{
int num = -1;//FF FF FF FF
int count = 0;
for(int i = 0;i < 32; i++)
{
//1 : 00 00 00 01
if(num & 1)
count++;
num >> 1;
}
return 0;
}
c
int main()
{
int num = -1;
int count = 0;
while(num)
{
count++;
num &= num - 1;
}//只是num - 1并不会让num的1减少,而减一后再与原来的数按位与就一定会让二进制的1减少一个。无论正数负数
return 0;
}
将数字的某个二进制位置0或置1
c
int main()
{
int num = 13;//00 00 00 0D D:1101
//将第五位置1,也就是01101 ->11101
num |= (1 << 4);
//再将第五位置0,也就是11101 -> 01101
num &= ~(1 << 4);
return 0;
}
五、逗号表达式
从左到右运算,结果为最后一个表达式的值
六、操作符的优先级和结合性
优先级
c3 + 4 * 5;优先级是 * > +所以先计算*
结合性
c6 * 7 / 2;结合性是从左到右,所以先计算6*7再计算/2;
优先级结合性参考表

七、整型提升
CPU中的整型运算器ALU,操作数一般是int的长度,所以在计算char,short 类型的数据时,会发生整型提升,然后再计算。
那么比int 大的整型呢?现代CPU有对应长度的运算器,以前没有的时候,就通过函数的方式完成。
cchar a = 1; char b = 2; char c = a + b;
如何整型提升
内存中存的是补码,所以负数高位补1,正数或无符号数高位补0,即可。
八、算术转换
双目操作符的两个操作数类型不一样,就会转换其中一种类型
clong double double float unsigned long int long int unsigned int int除此之外,还会考虑转换后的类型能不能表示全部的转换前的类型。
打个比方说,如果long 的大小是4字节而不是8字节,它无法表示所有的unsigned int 类型,所以long 会转换成 unsigned int 这是因为无符号数和有符号数相互运算时,如果占字节数相同,那优先将有符号转成无符号。
``
除此之外,还会考虑转换后的类型能不能表示全部的转换前的类型。
打个比方说,如果long 的大小是4字节而不是8字节,它无法表示所有的unsigned int 类型,所以long 会转换成 unsigned int 这是因为无符号数和有符号数相互运算时,如果占字节数相同,那优先将有符号转成无符号。
九、问题表达式
别写太复杂的表达式,什么自增自减后又相加,就不会有问题。


