C语言——结构体的内存对齐、位段

文章详细阐述了结构体的内存对齐规则,包括结构体成员的对齐方式和整体大小的计算,并通过实例解释了如何修改默认对齐数。同时,介绍了位段的概念,分析了位段的内存分配和跨平台问题,对比了位段与结构体的异同,强调位段在可移植性方面的挑战。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、结构体的内存对齐

观察下面不同类型的两个结构体的尺寸

typedef struct A
{
	int i1;//4
	char c1;//1
}A;

typedef struct B
{
	char c2;//1
	int i2;//4
	char c3;//1
}B;

int main()
{
	A a = { 0 };
	B b = { 0 };

	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(b));
	return 0;
}

运行结果:

在这里插入图片描述

这两个结构体所占的内存大小与预想的不一样,为什么呢?

1.结构体的对齐规则

结构体的内存对齐就是拿空间来换取时间

(1)第一个成员

放在结构体变量在内存中存储位置的0偏移处开始

(2)从第2个成员往后的所有成员

都放在一个对齐数的整数倍的地址处

注: 对齐数 = 编译器默认的一个对齐数与该成员大小二者的较小值(VS环境中默认的对齐数是8;Linux环境没有默认对齐数,对齐数就是成员自身大小)

(3)结构体总大小

为最大对齐数的整数倍

(4)如果嵌套了结构体的情况

嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍

2.例子:分析以下结构体的内存

typedef struct A
{
    char c;//1
    int i;//4
    double d;//8
    //现存 char 后,int 存到偏移量为 4(对齐数) 的整数倍的地址处
}A;

int main()
{
    A a = { 0 };
    printf("%d\n", sizeof(a)); //16
    return 0;
}

对这个结构体 A

在这里插入图片描述

3.修改默认对齐数

预处理指令 #pragma

#pragma pack(n)

就是将默认对齐数改为n,n取(1, 2, 4, 8, 16) 中任意一个值

例如以下修改方式:

typedef struct A
{
    char c1;//1
    int i;//4
    char c2;//1
}A;

#pragma pack(2)    //表示将默认对齐数改为2
typedef struct B
{
    char c1;//1
    int i;//4
    char c2;//1
}B;
#pragma pack()    //表示取消修改过的默认对齐数

int main()
{
    A a = { 0 };
    printf("%d\n", sizeof(a));

    B b = { 0 };
    printf("%d\n", sizeof(b));
    return 0;
}

运行结果:结构体A对齐数没变,为8,得到尺寸是12;结构体B对齐数改为2,得到尺寸是8

在这里插入图片描述

二、结构体实现位段的能力

1、位段

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

  • 位段的成员必须是 int、unsigned int、char 类型
  • 位段的成员名后边有一个冒号和一个数字 (冒号后的数字表示成员占几个bit位)

例如:

struct A
{
	int a : 2;//成员占2个bit位
	int b : 5;//成员占5个bit位
	int c : 10;
	int d : 30;
}

A就是一个位段类型

2、位段的内存分配

位段的空间上是按照需要以4个字节(int)或1个字节(char)的方式来开辟的

struct A
{
    int a : 2;//成员占2个bit位
    int b : 5;//成员占5个bit位
    int c : 10;
    int d : 30;
};
//先开辟4个字节即32个bit位,然后分配,不够就再开辟4字节空间
int main()
{
    printf("%d\n", sizeof(struct A));//8
    return 0;
}

位段涉及很多不确定因素(下面提到有四个不确定因素),位段是不跨平台的,注意可移植的程序应该避免使用位段

3、位段的跨平台问题

1.int位段被当成有符号还是无符号数是不确定的

2.位段中最大位的数目不能确定(16位机器最大16,32位机器最大32,比如30在16位机器会出问题)

3.位段中的成员在内存中从左向右分配,函数从右向左分配标准尚未定义

4.当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的

4、位段和结构的比较

与结构相比,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青春无限坑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值