为了账号安全,请及时绑定邮箱和手机立即绑定

【九月打卡】第6天【养成记】嵌入式挑战第6天,C语言中的运算符:位运算符、赋值复合运算符、逗号运算符和三目运算符、运算符优先级

标签:
嵌入式

课程章节:

课程名称:物联网/嵌入式工程师
章节名称:第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语言中的位运算等操作。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消