当前位置 博文首页 > jtwqwq的博客:翁恺老师C语言程序设计网课(15)

    jtwqwq的博客:翁恺老师C语言程序设计网课(15)

    作者:[db:作者] 时间:2021-08-19 09:50

    13.2.1 按位运算

    按位运算,即把整数当做二进制进行运算。

    ·&按位的与
    ·|按位的或
    ·~按位取反
    ·<<左移
    ·>>右移

    按位与 &
    如果(x)_i==1且(y)_i==1,那么(x&y)_i=1(第i位)否则=0
    如:
    0101 1010 5A
    1000 1100 8C 做运算后:
    0000 1000 08
    按位与的应用:

    1. 让某一位或某些位=0,如x & 0xFE(1111 1110) 会让最后一位变为0

    2. 取某个数中的某一段:如x & 0xFF (在32位int中是 0000 0000 0000 0000 0000 0000 1111 1111)这样只会留下最后8位
      按位或
      应用:

    3. 使得某一位/某几位变为1: x | 0x01

    4. 把两个数拼起来: 0x00FF | 0xFF00

    按位取反:0变为1,1变为0
    和补码不太一样,补码是用1 0000 0000-该数。可以试下(char)~c和(char)-c的值。
    逻辑运算,相当于把所有非0值变为1后做按位运算。
    因此还是有不同的,如果忘记逻辑运算是两个&|的话就会出问题。
    按位异或^,两位相等结果为0,两位不等结果为1.
    对同一个值做两次异或,还是原来的值。可以拿来做加密的编码,也可以判断两段码是否相等。

    13.2.2 移位运算

    i<<j:i中所有位向左移动j个位置,右边填入0
    所有小于int的类型,移位以int的方式做,结果是int。
    往左移1位就等价于乘了2.最多移动多少位取决于int的大小。x<<1
    右移相当于/2。
    对于小于int的类型,移位以int的方式做,且结果是int;
    对于unsigned类型,左边填0
    对于signed类型,左边填入原来的最高位(判断符号的01),保持符号不变。而往左移动的时候是不管符号位的。
    移位的位数不要用负数,这是没有定义的行为!

    13.2.3 位运算例子

    有什么用处?
    例1:输出一个数字的二进制在这里插入图片描述
    unsigned后面没有跟类型,则是默认为unsigned int。
    mask依次是
    1000 0000
    0100 0000
    0010 0000

    在这里插入图片描述
    这样每一位依次取余,看每一位。
    另外一件事:做单片机时常遇到这样的特殊功能寄存器(SFR)
    在这里插入图片描述
    怎么把对应比特置为0或1?
    在这里插入图片描述
    第几位就是1u<<几
    如SBS是1,左移2位是100
    PE是1,左移3位是1000
    100
    1000
    1100(或后得到的结果)
    用或使某些比特为1,用和使某些比特为0。

    13.2.4 位段

    在SFR表中可知,有的也不止一个比特。但之前的技巧只能控制一个比特。
    如何控制多个比特?位段,把一个int的若干位组合成一个结构。
    在这里插入图片描述
    冒号后面的数字表示 该成员占几个比特。
    在这里插入图片描述
    prtBin函数就是刚刚看过的输出二进制位。
    输出:sizeof(uu)=4
    二进制输出后五位10010
    当我们把uu.trailing=0注释掉后,sizeof(uu)没变,但是二进制位输出变了。后五位仍然是10010,前面没有赋初值(没有让trailing=0),是乱七八糟的0和1.
    当我们int trailing=32,仍然让uu.trailing=0,这时sizeof(uu)=8(所有位数加起来超过了32,所以用两个int来表达)二进制输出仍然只有后五位10010.
    位段可以直接用位段的成员名称来访问,比移位、与、或还要方便。
    编译器会安排其中的位的排列,不具有可移植性(比如老师的例子是从最右边排起,可能自己试验时会从最左边排。)所需要的位超过一个int时会安排多个int。
    总而言之,位段是操作和硬件相关的底层操作。

    cs