美文网首页
C语言中的位运算

C语言中的位运算

作者: simonycshi | 来源:发表于2019-03-31 20:55 被阅读0次

    C语言中的位运算

    • 结构体是唯一一种允许控制内存位(bit)的数据结构,称作位域(Bit Field)
    • 位域不能离开结构体单独存在
    • 位域不能成为数组,但是带位域的结构体可以成为结构体数组
    • 和位域有关的代码是取决于具体机器
    • 用途
      • 谨慎使用内存时(需要把几个数据放进一个字(Machine Word)
      • 读取非标准格式(9-Bit 整型)
      • ...

    位域

    struct { 
        unsigned int a : 1; //a占1为bit,最大为2^1 - 1 = 1
        unsigned int b : 3; //b占3位bit,最大为2^3 - 1 = 7
        unsigned int c : 1; //c占1位bit,最大为2^1 - 1 = 1
    } exmpl;
    
    • 位域是int或者unsigned int类型
    • 一位大小的位域只能是unsigned int,因为没有符号的空间
    • 在内存中位域被调整成int的大小(大部分机器中4 Bytes)

    用例:假设有一种机器人使用1 Byte大小的数据包进行通信,但是需要发送多个状态信息

    struct device { 
        unsigned int active : 1; 
        unsigned int ready : 1; 
        unsigned int idle : 1; 
        unsigned int error : 1; 
    } code;
    
    内存位置

    位域也可以匿名:

    struct device { 
        unsigned int active : 1;
        unsigned int ready : 1;
        unsigned int idle : 1;
        unsigned int error : 1;
        unsigned int : 2;
        unsigned int EOR : 1;
    } code;
    ```[图片上传失败...(image-a26aed-1554036927678)]
    
    # 位域的大小
    ```c
    //exmpl占12 Bytes
    struct { 
        unsigned int a : 1;
        unsigned int b : 32;
        unsigned int c : 1;
    } exmpl;
    
    • 首先给a分配内存空间,计算机将位域看作int(4 Bytes)分配空间,在第一个int中存储a后还有31位
    • 给b分配空间时,因为第一个int剩下的31位无法存储32位的b,所以计算机开辟第二个int来储存b
    • 第二个int已经没有多余的空间储存c,计算机单独再给c开辟一个int的空间
    //exmpl占8 Bytes
    struct { 
        unsigned int a : 1;
        unsigned int b : 1;
        unsigned int c : 32;
    } exmpl;
    
    • 首先给a分配内存空间,计算机将位域看作int(4 Bytes)分配空间,在第一个int中存储a后还有31位
    • 然后给b分配空间,因为第一个int还剩下的31位,在第一次开辟的空间中连续存储1位的b,
    • 第一个int已经没有多余的空间(还剩30位)储存c(32位),计算机单独再给c开辟一个int的空间

    按位运算符

    各种语言中的位运算符
    • 位运算符通常被用来:测试位、设置位、移位
    • 只有int(char)类型才可以用来位运算(一般使用char来处理bytes,int来处理words)



    逻辑运算和位运算
    • 按位NOT就是反转位(1's complement)
    • 按位XOR就是当且仅当一个操作数为1时,按位XOR才为1
    • 逻辑运算的结果是0非0,但是位运算的结果是02^n - 1(n为一个machine word含有的位数)

    位运算的用途

    1. 追踪错误
    • 奇偶校验(Parity Check)是一种校验代码传输正确性的方法。根据被传输的一组二进制代码的数位中“1”的个数是奇数或偶数来进行校验
    char get_char_from_modem(void) {
        char ch;
        ch = read_modem (); // 从Modem中读取一个数据  
        return (ch & 127); 
    }
    
    奇偶校验数据
    • 将bytes的第一位设置为校验位(标示剩下的7位中有1的数目是否位偶数)
    • 判断校验位后,使用按位与127复制除了校验位以外的位数



    2. 使用按位XOR寻找不同的位数

    int x = 120; 
    x = 127 ^ x;
    
    不同的位数
    • x为120,即差的数为7(127-120)



    3. 使用求反来加密数据

    数据加密

    其他操作

    1. 16进制表示

    #include <stdio.h> 
    int main(){ 
        int n = 0x01A1; 
        n = n & 0xFF; /* Note: n &= 0xFF; is the same */        
        printf("%x\n",n); return 0; 
    }
    
    //输出:a1
    
    16进制表示



    2. 使用Bit Mask检查16进制的具体位数

    //检查整数y右边的第三位是1还是0
    int mask = 0x0004; 
    if ((y & mask) == 0)
        printf("Third bit = 0\n"); 
    else
        printf("Third bit = 1\n");
    
    Bit Mask检查



    3. 使用Bit Mask修改部分位数:

    //让左边的4位归零,右边的4位不动
    char cmask = 0x0F; 
    c &= cmask;
    
    修改部分位数



    4. 移位操作:

    • 对于左移位,全部填充的位数都是0,
    • 对于右移位,如果标示位(第一位)是0,则全部填充0;如果标示位是1,则取决于具体实现,通常情况下填充1
    • 数值上左移位乘2的次方倍,反之除
    int n = 0x01A1; 
    int n1, n2, n3, n4;
    n1 = n << 1; /* Value of n1 = 0x0342 */
    n2 = n << 4; /* Value of n2 = 0x1A10 */
    n3 = n >> 1; /* Value of n3 = 0x00D0 */
    n4 = n >> 4; /* Value of n4 = 0x001A */ 
    
    移位操作

    相关文章

      网友评论

          本文标题:C语言中的位运算

          本文链接:https://www.haomeiwen.com/subject/ibzubqtx.html