位域

来源:互联网 发布:c语言编程软件教程 编辑:程序博客网 时间:2024/04/29 18:51

 

   1.一个位域的大小可以超过一个字节,大小不要超过其声明的类型大小即可:  如: 
       int name:31;
    2.如果相邻位域的类型相同,且其位宽之和小于等于类型的sizeof大小,则两位域放入一个字段存储:
          如:  
             char name1 : 2;
             char name2 : 6; 
     则这2个字段放入一个字节存储, sizeof结果为 1.
       3.如果相邻位域的类型相同,且其位宽之和大于类型的sizeof大小,则第二个位段从下一个对齐开始存储:
          如 :
             char name1 : 5;
             char name2 : 4;
     则这2个字段放入两个字节存储,sizeof结果为 2.
       4.如果相邻位域的类型不同,则这多个位段会存储在类型sizeof大的位段中,如果所有位段大小之和
          小于等于最大类型的sizeof,则可以全部装下,否则,整个位域的存储空间会以最大类型的sizeof长度
          来进行扩充 :
      如 :
        struct str{
            char name1 :1;
            int  name2 :30;
            char name3 :x;
        };
      当 x = 1时, sizeof(str) = 4;
      当 x = 2时, sizeof(str) = 8;
    5.如果你要使用位域,你应该很清楚每个字段的大小,从而有序的安排位域的顺序,最小化总字段空间:
      如 :
       struct str{                            struct str{
            char name1 : 4;                           char name1 : 4;
            char name2 : 5;                           char name3 : 4;
            char name3 : 4;                           char name2 : 5;
       };                                         };
       sizeof(str) = 3;                     sizeof(str) = 2;
关于空域:                       占位域:
struct str{                      struct str{
    int name1 : 5;               int name1 : 5;
    int :0;                             int :2;
    char name2 : 5;            char name2 : 5;
};                                    };
sizeof(str) = 8;                sizeof(str) = 4;      gcc      
sizeof(str) =8;           sizeof(str) = 8;   vc6.0
空域和占位域均不能使用
可以有意使某位域从下一单元开始,比如利用空域和无位域名的位域。
如果相邻位域类型不用,则vc6采取不压缩方式,dev-c++ 和GCC都采取压缩方式。
如:
struct T0
    
{
        
char c:2;
        
int i:1;
    }
;
cout 
<< "struct T0{ char c:2; int i:1;} = " << sizeof(T0) << endl; //dev c++:4  vc6:8
i成员相对于结构体首地址的偏移应该是4的整数倍,所以c成员后要填充3个字节,然后再开辟4个字节的空间作为int型,其中4位用来存放i,所以上面结构体在VC中所占空间为8个字节;而对于采用压缩方式的编译器来说,如果填充的3个字节能容纳后面成员的位,则压缩到填充字节中,不能容纳,则要单独开辟空间,所以上面结构体T0在GCC或者Dev-C++中所占空间应该是4个字节。

typedef  struct  tag
{

         char  hour :  4 ;
        unsigned second :  6 ;
        unsigned minute :  6 ;
}Time;

printf( " %d " ,  sizeof (Time));

在gcc下的输出是4,在vc下的输出是8。

原 因是gcc把unsigned类型当成unsigned short来处理,Time.hour和Time.second共同占用一个unsigned short单元,minute独占一个unsigned short单元,再加上对其所需的空白,总共是2个unsigned short, 则sizeof为4。

而VC把位域的unsigned类型当做unsigned int,所以Time占用2个unsigned int,sizeof值为8。

 

 

示例

下面是一段在论坛上发现的代码,

union   
{
     struct  
    {
         char  a :  1 ;
         char  b :  2 ;
         char  c :  3 ;
    }d;

     char  e;
}f;

f.e =   1 ;
printf( " %d " , f.d.a);

Intel x86的机器是按little-endian的字节顺序存储数据(点击for详细),所以d中的位域在内存中放置顺序为 cccbba ,

当执行完 f.e = 1 这条语句后,d的最低有效位(及位域a)的值为1。

这时我就出现了疑问,为什么打印的最后结果是-1而不是1?

不过最后终于解决了这个问题,因为位域a定义的类型是signed char,是一个有符号数,所以尽管a只有1位,还是要进行符号扩展。1是做为补码存在,加一再取反就得到值-1。

如果将a的类型定义为unsigned char即可得到结果为1。

 

查看:http://bbs.suda123.com/Archiver/webbiancheng/thread-252105-1.html

 

原创粉丝点击