位段

位段

知识点概要:

  • 什么是位段
  • 位段的内存分配
  • 位段的跨平台问题
  • 总结

什么是位段

位段的声明和结构是类似的,有两个不同:

  1. 位段的成员必须是 int 、unsigned int、signed int 。
  2. 位段的成员名后面有一个冒号和数字。(这个数字用来限定这个成员所占内存的bit位)
1struct S1
{
    int _a : 2;
    int _b : 5;
    int _c : 10;
    int _d : 30;
};
printf("%d\n", sizeof(S1)); // 8

解析:

_a 占了2位,_b占了5位,_c占了10位,加起来用了17位,剩余15位,不够存放_d的30位,所以重新开辟一个的int型(32位),并从起始位置开始存放_d。如下图所示:
位段_第1张图片
所以,该位段的大小为 2int = 8字节

位段的内存分配

  1. 位段的成员可以是 int、unsigned int、signed int 或者是 char (属于整型家族)类型。
  2. 位段的空间上是按照需要以4个字节(int)或者1个字节(char)的方式来开辟的。
  3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。
2struct S2
{
    char a : 3;
    char b : 4;
    char c : 5;
    char d : 4;
};
int main()
{
    struct S2 s2;
    printf("%d\n", sizeof(s2)); // 3
    s2.a = 1;
    s2.b = 2;
    s2.c = 3;
    s2.d = 4;
    return 0;
}

解析:

a占了3位,b占了4位,加起来占了7位,剩余1位不够存放c,所以再开辟一块char型空间(8bit)并从起始位置来存放c,c占了5位,剩余3位不够存放d,所以还得再开辟一块char型空间(8bit)并从起始位置来存放d。如下图所示:
位段_第2张图片
所以,位段的大小为 3char = 3字节。
通过对其各个成员赋值,看它的内存分配如下图:
这里写图片描述
a和b占用第一个字节;c占用第二个字节;d占用第三个字节。

3:不同类型

typedef struct S3
{
    unsigned char b : 1;
    unsigned int a : 1;
    unsigned int c : 1;
    unsigned int d : 2;
    unsigned int e : 2;
}S3;

int main()
{
    S3 s3;
    printf("%d\n", sizeof(s3)); // 8
    s3.b = 1;
    s3.a = 1;
    s3.c = 1;
    s3.d = 1;
    s3.e = 1;
    return 0;
}

解析:

char b 占了一个一个字节的1bit,接下来存放int a,但为了内存对齐,要向后偏移3个字节,再开辟了一个int 型空间(32bit),a占了1位,c占了1位,d占了2位,e占了2位。如下图所示:
位段_第3张图片
所以,该位段的大小为 1+3+4=8字节
通过对其各个成员变量赋值,看它的内存分配如下图:
这里写图片描述
b占用第一个字节,a、c、d、e占用第5、6、7、8个字节

4:例3的变形

typedef struct S4
{
    unsigned int a : 1;
    unsigned char b : 1;
    unsigned int c : 1;
    unsigned int d : 2;
    unsigned int e : 2;
}S4;

int main()
{
    S4 s4;
    printf("%d\n", sizeof(s4));
    s4.a = 1;
    s4.b = 1;
    s4.c = 1;
    s4.d = 1;
    s4.e = 1;
    return 0;
}

解析:

int a 占了1bit,由于第二个类型为char型,所以得再开辟一个char型空间(8bit)来存放char b,接下来存放int c,但为了内存对齐,要向后偏移3个字节,再开辟了一个int 型空间(32bit),c占了1位,d占了2位,e占了2位。如下图所示:
位段_第4张图片
所以,该位段的大小为 int + char +偏移的3字节 + int =4+1+3+4=12字节
通过对其各个成员变量赋值,看它的内存分配如下图:
位段_第5张图片
a占用了前4个字节,b占用了第5个字节,c、d、e占用了第6、7、8个字节。

位段的跨平台问题

  1. int 位段被当成有符号数还是无符号数是不确定的。(只有被当成无符号数时,结果才是正确的)
  2. 位段中最大位的数目不能确定。(16位机器最大16位,32位机器最大32位)
  3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
  4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃还是利用,这是不确定的。

总结

  • 跟结构体相比,位段可以达到同样的效果,它可以很好的节省空间,但是有跨平台的问题存在。
  • 用位段可以实现IP地址的快速提取与转化。

你可能感兴趣的:(C语言)