美文网首页
C高阶1:二进制操作

C高阶1:二进制操作

作者: jdzhangxin | 来源:发表于2019-04-14 09:07 被阅读0次

    1. 位运算

    1. 按位运算

      No. 操作符 功能
      1 & 按位与
      2 | 按位或
      3 ~ 按位取反
      4 ^ 按位异或
    2. 运算规则

      p q p & q p | q p ^ q
      0 0 0 0 0
      0 1 0 1 1
      1 1 1 1 0
      1 0 0 1 1
    3. 示例

      1. 按位与
        让某一位或某些位为0

        int n = 0xFFFF;
        n = n & 0x0010;
        

        截取二进制数中的一段值。

        int n = 0xFFab;
        n = n & 0x00FF;
        
      2. 按位或
        让某一位或某些位为1

        int n = 0x0000;
        n = n | 0x0010;
        

        拼接两个二进制数。

        int a = 0xab00;
        int b = 0x0012;
        int c = a|b;
        
      3. 按位取法
        得到全部为1的数字~0

        int n = ~0;// 等同于0xFFFF
        

        使数字的部分清零x& ~7

        int n = 0xFFFF;
        n = n & ~7;
        
      4. 按位异或
        两个相等数异或结果为0

        int n = 0x1234;
        n = n^n;
        

        对同一个变量两次异或,变会原值。

        int a = 0x1234;
        int b = 0x1357;
        a = a^b;
        a = a^b;
        

    逻辑运算与按位运算

    1. 逻辑运算结果只有01两种值,按位运算有多种值。
    2. 逻辑运算相当于把所有的非零值都变成1,再按位运算。
    1. 练习

    2. 移位运算

    No. 操作符 功能
    1 << 左移
    2 >> 右移
    1. 左移
      i<<j表示i中所有位向左移动j个位置,右边填入0
      所有小于int的类型,移位以int大小执行,结果为int

    2. 右移
      i>>j表示i中所有位向右移动j个位置,
      对于unsigned类型,左边填入0;对于signed类型,左边填入符号位。
      所有小于int的类型,移位以int大小执行,结果为int

    3. 位移运算与乘除运算
      位移运算与乘除运算运算有如下对应关系:

      No. 位移运算 乘除运算
      1 x<<1 x*2
      2 x>>1 x/2
      3 x<<n x*pow(2,n)
      4 x>>n x/pow(2,n)
      5 x<<=1 x*=2
      6 x>>=1 x/=2
      7 x<<=n x*=pow(2,n)
      8 x>>=n x/=pow(2,n)
    • 试一试
      x<<-2;// 未定义行为
      
    • 练习
      1. 位的设置
        i |= 1<<j;
        
      2. 位的清除
        i &= ~(1<<j);
        
      3. 位的测试
        i & 1<<j
        
    • 实践
      用位表示下面的结构体。
    typedef struct{
        bool student; // true:表示学生,false:表示非学生
        bool sex; // true:表示男,false:表示女
        bool pass; // true:表示合格,false:表示不合格
    };
    

    3. 位域

    3.1 位域是什么?

    位域是又称作位段,是把一个字节中的二进位划分为几个不同的区域。

    3.2 位域有什么用?

    节省空间,有些信息不需要占用一个完整的字节。

    3.3 位域怎么用?

    1. 定义位域
      定义位域与结构定义相仿。

      • 语法
        struct 位域结构名{ 
            类型 位域名:位域长度;
        };
        
        为了保证位域的可以移植性,成员类型通常为unsigned intint,C99可以使用bool
      • 示例
        struct Byte{
          unsigned int b1:1;
          unsigned int b2:1;
          unsigned int b3:1;
          unsigned int b4:1;
          unsigned int b5:1;
          unsigned int b6:1;
          unsigned int b7:1;
          unsigned int b8:1;
         };
        
    2. 位域变量
      定义和使用位域变量与结构体相同。每个域有一个域名,允许在程序中按域名进行操作。

      void printByte(struct Byte a){
        printf("%d",a.b1);
        printf("%d",a.b2);
        printf("%d",a.b3);
        printf("%d",a.b4);
        printf("%d",a.b5);
        printf("%d",a.b6);
        printf("%d",a.b7);
        printf("%d\n",a.b8);
      }
      int main () {
      struct Byte a;
      printByte(a);
      struct Byte b = {1,0,1,0,1,0,1,0,};
      printByte(b);
      return 0;
      }
      

      试一试

      struct Byte c = {1,2,3,4,5,6,7,8,};
      printByte(c);
      
      void scanfByte(struct Byte* a){
      scanf("%d",&a.b1);
      scanf("%d",&a.b2);
      scanf("%d",&a.b3);
      scanf("%d",&a.b4);
      scanf("%d",&a.b5);
      scanf("%d",&a.b6);
      scanf("%d",&a.b7);
      scanf("%d",&a.b8);
      }
      
    3. 位域大小

      printf("sizeof(Byte) = %ld\n",sizeof(Byte));
      
      struct Byte{
          unsigned char b1:1;
          unsigned char b2:1;
          unsigned char b3:1;
          unsigned char b4:1;
          unsigned char b5:1;
          unsigned char b6:1;
          unsigned char b7:1;
          unsigned char b8:1;
      };
      

      位域的存储由编译器实现决定。编译器规定存储单元大小(8位、16位、32位)。 编译器会把位域逐个放入存储单元,位域之间没有间隙,直到存储单元放不下下一个位域,然后从下个存储单元继续存放。也有编译器跨存储单元存放。存放顺序也是编译器决定。
      整个结构体的总大小为最宽基本类型成员大小的整数倍。

    相关文章

      网友评论

          本文标题:C高阶1:二进制操作

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