位域实践

有如下代码:

   1:  #include <stdio.h>
   2:   
   3:  #include <string.h>
   4:   
   5:  #include <malloc.h> 
   6:   
   7:  #include <stdlib.h> 
   8:   
   9:  typedef struct AA 
  10:   
  11:  { 
  12:   
  13:  int b1:5; 
  14:   
  15:  int b2:2; 
  16:   
  17:  }AA; 
  18:   
  19:  int main(){
  20:   
  21:  AA aa; 
  22:   
  23:  char cc[100]; 
  24:   
  25:  strcpy_s(cc,"0123456789abcdefghijklmnopqrstuvwxyz\0");
  26:   
  27:  printf("%d\n",sizeof(cc));
  28:   
  29:  printf(" %d \n",sizeof(AA)); 
  30:   
  31:  memcpy(&aa,cc,sizeof(AA)); 
  32:   
  33:  printf("aa.b1 = %d\n",aa.b1);
  34:   
  35:  printf("aa.b2 = %d\n",aa.b2);
  36:   
  37:  system("pause");
  38:   
  39:  }

运行结果:

clip_image001

当时对这个结果非常的费解,memcpy(&aa,cc,sizeof(AA)); 将会从数组cc中拷贝4个字节到结构体aa中,拷贝过后的结果如下图所示,其中的0x30、0x31、0x32、0x33分别是"0123"的

码(注意:字符在内存中是按照ASCII值存放的)。

clip_image002

由于intel是Little endian(小高高),小端格式+高位存放在高地址,所以b1和b2一起占据了第一个字节的前七位,由于第一字节0x30=0011 0000,所以b1=1 0000,b2=01,由于在输出的时候要进行符号位的扩展,所以b1=0xffff fff0=-16,b2=0x0000 0001=1,这就是上面的输出结果。

下面的截图来自:C: in a nutshell

clip_image003

其实我们可能不希望由于符号位的扩展而导致正数变成负数,这就需要将位域的类型定义为unsigned int,如下所示:

clip_image004

这样输出结果就是16和1了,如下图所示:

clip_image005

位域的大小

clip_image004[1]

上面结构的大小是4.

clip_image006

上面结构的大小是1.

以上结果都是在VS2008中得到的。

空位域:

定义为unsigned int :0,表示从下一个边界开始存放。

clip_image007

clip_image008

Sizeof(AA)为:16

clip_image009

如果不用空位域,着sizeof(AA)为12,如下图所示:

clip_image010

注意:每一个位域的大小不能够超过了其自身类型的大小,如下面的定义是错误的:

clip_image011

参考资料:

  1. http://happyhaoyun.blog.163.com/blog/static/2119926020107311329801/
  2. http://space.itpub.net/14805538/viewspace-483697

原文地址:https://www.cnblogs.com/justinzhang/p/2109943.html