0%

位段

文章时效性提示

本文发布于 505 天前,部分信息可能已经改变,请注意甄别。

什么是位段?
——位段是一种类似结构体的类型。

位段的声明和结构体类似,但有两点不同:

  • 位段的成员必须是int、unsigned int或signed int(可能也有char,但是一个位段的类型必须是类似的)
  • 位段的成员名后边有一个冒号和一个数字(意思是这个变量需要多少个比特位)

位段的内存分配

  • 位段的成员可以是int、unsigned int、signed int或者是 char类型
  • 位段的空间上是按照需要以4个字节(int)或1个字节(char)的方式来开辟的
  • 位段涉及很多不确定因素,不跨平台,注重可移植性程序不使用位段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
//位段 - 二进制位
struct S
{
    int a : 2;//需要2个比特位
    int b : 5;//需要5个比特位
    int c : 10;//需要10个比特位
    int d : 30;//需要30个比特位
};
int main() {
    struct S s;
    printf("%d\n",sizeof(s));//8
    return 0;
}

打印的结果是s使用8字节空间。
首先开辟一个4字节的空间,共32bit,先给a,b,c分配共17bit的空间,剩下的空间不够给d分配30bit的空间,剩余空间丢弃。
另开辟一块4字节的空间,共32bit,给d分配30bit的空间,剩下2bit的空间丢弃,所以位段s占8字节。
注意⚠️:位段后面的数字不能大于32。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
struct S
{
    char a : 3;
    char b : 4;
    char c : 5;
    char d : 4;
};

int main()
{
    struct S s ={0};
    s.a = 10;//10的二进制是1010,但a这个空间只存的下3个比特位,只能存的下010,也就是2
    s.b = 20;//20的二进制是10100,b只有4比特位,存0100。
    s.c = 3;
    s.d = 4;
    return 0;
}

位段的跨平台问题

位段不跨平台,主要由下面四点导致:

  • int位段被当成有符号还是无符号数是不确定的。
  • 位段中最大位的数目不能确定。(16位机器最大16,32位机最大32,写成27,在16位机器会出问题。)
  • 标准未定义位段在内存中的分配规则,不知道从左往右还是从右往左分配
  • 一个结构包含两个位段,第二个成员较大时,无法容纳第一个位段剩余位时,剩下的空间舍弃或保留不确定。