课程名称:物联网/嵌入式工程师
章节名称:第1周之第三讲 3-6 C语言中的运算符:位运算符、赋值复合运算符、逗号运算符和三目运算符、运算符优先级
讲师姓名:大白老师
运算符 | 格式 | 功能 | 结果 |
---|---|---|---|
& | 表达式1 & 表达式2 | 按位与 | 1按位与1结果是1 1按位与0结果是0 0按位与0结果是0 速记: 都1则1,1零则0 |
❘ | 表达式1 ❘ 表达式2 | 按位或 | 1按位或0结果是1 1按位或1结果是1 0按位或0结果是0 速记: 有1则1,都0则0 |
^ | 表达式1 ^ 表达式2 | 按位异或 | 相同为0,不同为1 |
~ | ~表达式 | 按位取反 | 1变成0, 0变成1 |
运算符 | 格式 | 功能 | 结果 |
---|---|---|---|
<< | 表达式 << 位数 | 左移 | 无论是正数还是负数,左移都是对应的二进制位向左移动高位丢弃,低位补0 左移的时候,等价于将这个数据乘以2的n(移动的位)次方 |
>> | 表达式 >> 位数 | 右移 | 逻辑右移(针对无符号数据) 对应的是正数和0,逻辑右移是对应的二进制位向右移动,低位丢弃,高位补0。 算术右移(针对有符号数据): 若是数据为正数,算术右移是对应的二进制位向右移动,低位丢弃,高位补0。 若是数据为负数,算术右移是对应的二进制位向右移动,低位丢弃,高位补1。 速记: 右移,向右移动,低位丢弃,高位正数补0,负数补1 |
#include <stdio.h> int main() { unsigned char reg1 = 0x13; unsigned char reg2 = 0x78; unsigned char data = 0; data = reg1 & reg2; printf("data = %#x => %d\n",data,data); data = reg1 | reg2; printf("data = %#x => %d\n",data,data); data = reg1 ^ reg2; printf("data = %#x => %d\n",data,data); data = ~reg1; printf("data = %#x => %d\n",data,data); return 0; }
分析:
0x13 => 0001 0011 0x78 => 0111 1000 & 0001 0000 => 0x10 => 16 | 0111 1011 => 4+2+1=7 8+0+2+1=11 => 0x7b => 123 ^ 0110 1011 => 4+2=6 8+0+2+1=11 => 0x6b => 107 0x13 => 0001 0011 ~ 1110 1100 => 14 12 => 0xec => 236
#include <stdio.h> int main() { unsigned char a = 10; // 0000 1010 unsigned char b = 15; // 0000 1111 8+4+2+1 unsigned char t = 0; // a ^ a // 0000 1010 //^ 0000 1010 // 0000 0000 // a ^ 0 // 0000 1010 //^0000 0000 // 0000 1010 printf("a = %d b = %d\n",a,b); a = a ^ b; b = a ^ b; // b = (a^b) ^ b => b = a ^ 0 => b=a a = a ^ b; // a = (a^b) ^ a => a = 0 ^ b => a=b printf("a = %d b = %d\n",a,b); return 0; }
#include <stdio.h> int main() { unsigned char reg = 3; char a = -3; reg = reg << 3; printf("reg = %d\n",reg); a = a << 3; printf("a = %d\n",a); a = a>>3; printf("a = %d\n",a); return 0; }
分析:
3 => 2+1 => 0000 0011 -3 => 源码:1000 0011 反码:1111 1100 补码:1111 1101 3 0000 0011 <<3 0001 1000 => 16 + 8 = 24 -3 1111 1101 <<3 补码:1110 1000 反码:1001 0111 +1 :1001 1000 => -24 补码:1110 1000 >>3 补码:1111 1101 反码:1000 0010 +1 :1000 0011 => -3
unsigned char a = 0x58; unsigned char b = 0xd7; unsigned char c = 0; 要求输出下列c的值。 c = a & b, c = a | b. c = (a & ~b) ^ 0xf1; 要求先笔算,然后书写代码验证。
代码:
#include <stdio.h> int main() { unsigned char a = 0x58; unsigned char b = 0xd7; unsigned char c = 0; c = a & b; printf("c = %#x => %d\n",c,c);// 0x50 80 c = a | b; printf("c = %#x => %d\n",c,c);// 0xdf 223 c = (a & ~b) ^ 0xf1; printf("c = %#x => %d\n",c,c);// 0xf9 249 return 0; }
分析:
a = 0x58 => 4+1=5 8 => 0101 1000 b = 0xd7 => d7 = 13 7 => 8+4+1=13 4+2+1=7 => 1101 0111 a 0101 1000 b 1101 0111 & 0101 0000 => 0x50 => 2^6+2^4=64+16=80 | 1101 1111 => 0xdf => 2^7+2^6+2^4+2^3+2^2+2^1+2^0 = 128+64+16+8+4+2+1 = 223 a&~b => ~b 0010 1000 => 0101 1000 => & 0000 1000 => 0xf1 => f=15 1 => 8+4+2+1=15 1 => 1111 0001 0000 1000 1111 0001 ^ 1111 1001 => 0xf9 => 2^7+2^6+2^5+2^4+2^3+2^0 = 128+64+32+16+8+1 = 249
运算符 | 功能说明 | 示例 |
---|---|---|
+= | 加法赋值复合运算符 | a+=b 等价于 a = a + b |
-= | 减法赋值复合运算符 | a-=b 等价于 a = a - b |
*= | 乘法赋值复合运算符 | a*=b 等价于 a = a * b |
/= | 除法赋值复合运算符 | a/=b 等价于 a = a / b |
%= | 求余赋值复合运算符 | a%=b 等价于 a = a % b |
&= | 位与赋值复合运算符 | a&=b 等价于 a = a & b |
❘= | 位或赋值复合运算符 | a❘=b 等价于 a = a ❘ b |
^= | 位异或赋值复合运算符 | a^=b 等价于 a = a ^ b |
>>= | 位右移赋值复合运算符 | a>>=b 等价于 a = a >> b |
<<= | 位左移赋值复合运算符 | a<<=b 等价于 a = a << b |
#include <stdio.h> int main() { int a = 20,b = 10; a += b; // a = a + b; => a = 30; printf("a = %d\n",a); //30 a *= b; //a = a * b; => 30 * 10 printf("a = %d\n",a); //300 return 0; }
练习
从键盘输入两个整数,要求输出+=,-=,*=,/=的结果
代码:
#include <stdio.h> int main() { int a,b,ret; printf("请输入两个整数:\n"); scanf("%d%d",&a,&b); printf("a = %d b = %d\n",a,b); ret = a+=b; printf("ret = a+=b => a = %d b = %d ret = %d\n",a,b,ret); ret = a-=b; printf("ret = a-=b => a = %d b = %d ret = %d\n",a,b,ret); ret = a*=b; printf("ret = a*=b => a = %d b = %d ret = %d\n",a,b,ret); ret = a/=b; printf("ret = a/=b => a = %d b = %d ret = %d\n",a,b,ret); return 0; }
#include <stdio.h> int main() { int a = 10,b = 20; int c = 0; int ret = 0; ret = a > b ? a+b : a-b; printf("ret = %d\n",ret); ret = a < b ? (a^=b ,b^=a ,a^=b) : a * b; printf("ret = %d\n",ret); ret = a < b ? (c = a,a = b,b = c) : a * b; printf("ret = %d\n",ret); return 0; }
定义三个整数a,b,c,用户从键盘输入赋值,从小到大,排列,然后输出 [不允许使用if语句] 最终输出,a保存最小值,b保存其次,c保存最大值 例如: 用户输入 a = 30,b = 20,c = 10.要求最终保存的结果为 a = 10,b = 20,c = 30.
代码:
#include <stdio.h> int main() { int a,b,c; printf("请输入三个整数:\n"); scanf("%d%d%d",&a,&b,&c); printf("输入:a = %d b = %d c = %d\n",a,b,c); a > b ? (a^=b,b^=a,a^=b) : a; a > c ? (a^=c,c^=a,a^=c) : a; b > c ? (b^=c,c^=b,b^=c) : b; printf("输出:a = %d b = %d c = %d\n",a,b,c); return 0; }
优先级 | 运算符及含义 | 结合规律 |
---|---|---|
1 | [ ] () -> 后缀++ 后缀– | 从左向右 |
2 | 前缀++ 前缀-- sizeof & * + -(负号) ~ ! | 从右向左 |
3 | 强制类型转换 | 从右向左 |
4 | * / % (算术乘除) | 从左向右 |
5 | + - (算数加减) | 从左向右 |
6 | << >> (位移) | 从左向右 |
7 | < <= > >= | 从左向右 |
8 | == != | 从左向右 |
9 | &(位逻辑与) | 从左向右 |
10 | ^(位逻辑异或) | 从左向右 |
11 | ❘ (位逻辑或) | 从左向右 |
12 | && | 从左向右 |
13 | ❘❘ | 从左向右 |
14 | ? : (三目运算符) | 从左向右 |
15 | = ^= /= %= += -= <<= >>= &= ^= != | 从右向左 |
16 | , (逗号运算符) | 从左向右 |
初等单目一二级 -> 初等运算符和单目运算符分别是第1、2优先级
乘除求余加减移 -> 这句里面的运算符全归为算术运算符,移表示移位
关系等于不等于 -> 关系运算符(< <= > >=)
按位与来异或或 -> 位运算符优先级顺序:& -> ^->l
逻辑与或条件弱 -> 逻辑运算符优先级顺序:&&->||,后面跟着优先级比较低(弱)的条件运算符
赋值逗号一点破 -> 赋值,逗号最低
通过了运算符学习,熟练掌握C语言中的位运算等操作。