C语言操作符(下)

📅 2026/7/27 17:37:17
C语言操作符(下)
文章目录一、移位操作符1. 左移操作符2. 右移操作符Ⅰ.算术右移Ⅱ.逻辑右移3. 移位的复合赋值运算符二、位操作符1. 按位与()2. 按位或(|)3. 按位异或(^)4. 按位取反(~)5. 位的复合赋值运算符三、操作符的结合性和优先级1. 优先级2. 结合性3. 操作符优先级表一、移位操作符注以下关于位的操作符讲解都是在32位机器平台下进行的。1. 左移操作符左移操作符也就是把所有的二进制位向左移动对应的位数。规则是左边移出(丢弃)右边补0。例如#includestdio.hintmain(){intnum10;intnnum3;printf(n %d\n,n);printf(num %d\n,num);return0;}运行结果我们知道数据在计算机中都是以补码的形式来存储的所以num10在左移3位后得到的还是补码(00000000 00000000 00000000 01010000)又因为正整数的原反补码是一样的所以正整数10左移三位后得到的二进制数转换成十进制数为80且num的值没有改变通过输出结果可以看出。2. 右移操作符右移操作符把所有的二进制位向右移动对应的位数。右移分为逻辑右移和算术右移●逻辑右移左边用0填充右边移出(丢弃)●算术右移左边用原该值的符号位填充右边移出(丢弃)Ⅰ.算术右移#includestdio.hintmain(){intnum10;intnnum1;printf(n %d\n,n);printf(num %d\n,num);return0;}运行结果这里得到的运行结果是n5但是你看不出是逻辑右移还是算术右移因为对于正整数不管是逻辑右移还算术右移左边补的都是0。我们再看一段代码#includestdio.hintmain(){intnum-1;intnnum1;printf(n %d\n,n);printf(num %d\n,num);return0;}运行结果通过输出结果可以看出num-1右移一位最高位补的是1所以这里是算术右移。在我使用的VS2022这个编译器上采用的就是算术右移。(大部分编译器都是算术右移)Ⅱ.逻辑右移逻辑右移就不用考虑符号位了不管是正整数还是负整数逻辑右移最高位补的都是0。-1和10通过逻辑右移一位后得到的还是补码只是逻辑右移后最高位补的是0不管是正整数还是负整数符号位都变成了0都会被当成正整数而正整数的原反补码相同。以有符号十进制数打印出来的结果就是2147483647和5。注意移位操作符的操作数只能是整数。⚠️警告对于移位运算符不要移动负数位这种是标准未定义的。(就像10-1这种是未定义的)3. 移位的复合赋值运算符我们讲过复合赋值运算符就是相应的算术运算符结合赋值运算符的一种简化那么对于移位操作符也是有复合赋值运算符的#includestdio.hintmain(){intnum110;intnum220;num11;num21;printf(num1 %d\n,num1);printf(num2 %d\n,num2);return0;}运行结果上面的 num11 其实就是 num1num11 的简化num21即num2num21。二、位操作符1. 按位与()通过一段代码来说明位与操作符#includestdio.hintmain(){intn-10;intm5;printf(%d\n,nm);return0;}运行结果按位与就是将两个整数所有对应的二进制位进行逐一比较同1则为1有0则为0得到的二进制数即为按位与后的结果。就像上面的 -10 5(注意整数在计算机中存放的是补码)所以n(-10) m(5)的结果就为00000000 00000000 00000000 00000100换算成十进制的整数就为4。2. 按位或(|)按位或就是将两个整数所有对应的二进制位进行逐一比较同0则为0有1则为1得到的二进制数即为按位或后的结果。#includestdio.hintmain(){intn-7;intm12;printf(%d\n,n|m);return0;}运行结果所以n(-7) | m(12)的结果就为11111111 11111111 11111111 11111101按位或得到的这个结果还是补码最高位是符号位换算成10进制的整数就为-3。3. 按位异或(^)按位异或的意思就是将两个整数所有对应的二进制位进行逐一比较相同为0相异为1。#includestdio.hintmain(){intn9;intm-13;printf(%d\n,n^m);return0;}运行结果所以n(9) ^ m(-13)的结果就为11111111 11111111 11111111 11111010按位异或得到的结果还是补码换算成十进制的整数就为-6。4. 按位取反(~)按位取反就是将整数的所有二进制位(bit)是1的变为0是0的变为1(包括符号位)。注意数据在计算机中存储的是补码。#includestdio.hintmain(){inta17;printf(%d\n,~a);return0;}运行结果按位取反是位操作符中唯一的单目操作符。需要注意按位取反是所有的二进制位都要取反(0变1,1变0)包括符号位。而原码变成反码的取反是符号位不变数值位按位取反。5. 位的复合赋值运算符同样的对于位操作符也是有复合赋值运算符的#includestdio.hintmain(){inta10;intb13;intc-5;a1;printf(%d\n,a);b|1;printf(%d\n,b);c^1;printf(%d\n,c);return0;}运行结果上面的a 1、b | 1、c ^ 1意思分别是a a1、b b|1、c c^1。就是位操作符结合赋值操作符的简化。注意对于上述位操作符的操作数必须得是整数。三、操作符的结合性和优先级C语言的操作符有2个重要的属性优先级、结合性。这两个属性决定了表达式求值的计算顺序。1. 优先级优先级指的是如果一个表达式包含多个运算符哪个运算符应该优先被执行。各种运算符的优先级是不一样的。2 3 * 4上面示例中表达式2 3*4里面既有加法运算符()又有乘法运算符(*)。由于乘法的优先级高于加法所以会先计算3*4而不是先计算23。2. 结合性如果两个运算符的优先级相同优先级没办法确定要先计算哪个这个时候就要看结合性了根据运算符是左结合还是右结合决定执行顺序。即当一个操作数两侧的运算符优先级相同时要看操作数与操作符的结合顺序。大部分运算符是左结合(从左到右执行)少数运算符是右结合(从右到左执行)比如赋值运算符()。5 * 4 / 2上面示例中* 和 / 的优先级是相同的所以对于中间的操作数4就要看与操作符 * 和 / 的结合性了因为 * 和 / 都是左结合性按照从左往右的结合方向。所以4先和*结合也就是先执行5*4的运算再执行 /2 的运算。3. 操作符优先级表下表整理了运算符的优先级和结合性文章若有不足的地方欢迎小伙伴们在评论区指正