字节对齐(c/c++) (仅供学习参考)

本文详细解析了结构体和共用体在内存中的布局原则,包括字节对齐准则及其在不同情况下的应用扩展,如结构体嵌套和包含数组的情况,并通过实例说明如何计算结构体和共用体的大小。

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

概述:

对于结构体:

字节对齐准则:
(1),结构体变量的首地址能够被其最宽基本类型成员大小所整除;
(2),结构体每个成员相对于结构体首地址的偏移量(offset)都是该成员大小的整数倍,如有需要,编译器会在成员之间加上中间填充字节;
(3),结构体总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上末尾填充字节。
第(2)、(3)条准则决定了结构体变量占据内存空间的大小。

知识扩展1:若出现结构体嵌套,则准则(2)、(3)应改为:
(2),复合成员相对于结构体首地址的偏移量是复合成员中最宽基本类型成员大小的整数倍;
(3),结构体总大小为结构体最宽基本类型成员大小整数倍。

知识扩展2,若结构体内部出现数组,则准则2应为:
(2),数组相对于结构体首地址的offset是该数组成员大小的整数倍。

对于共用体:
原则上,共用体大小取决于占据最多内存的成员的长度。但字节对齐准则(3)仍然成立。



详情请参照以下分析:

对于结构体:

首先理解字节对齐准则:
(1),结构体变量的首地址能够被其最宽基本类型成员大小所整除。
(2),结构体每个成员相对于结构体首地址的偏移量(offset)都是该成员大小的整数倍,如有需要,编译器会在成员之间加上中间填充字节。
(3),结构体总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上末尾填充字节。

第(2)、(3)条准则决定了结构体变量占据内存空间的大小。

基本类型指:char,short,int,float,double。

数据宽度即其sizeof的大小。

eg:
struct {char c; short s; float f;}A;
struct{char c; float f; short s;}B;
则sizeof(A)=?,sizeof(B)=?

解:A中,char占1字节,short占2,则short相对于结构体首地址的offset(偏移量)=1,为满足准则(2),必须添加中间填充字节1;

float占4字节,相对于结构体首地址offset=(1+1+2)(红色为填充部分)即4,满足准则(2);

此时结构体大小为(1+1+2+4)=8(红色为填充部分),是最宽基本类型float整数倍,满足准则(3)。

所以可得出:sizeof(A)=8。

对于B:B中,char占1,float占4,则float相对于结构体首地址的offset=1,为满足准则(2),必须添加中间填充字节3;

short占2,相对于结构体首地址offset=(1+3+4)(红色为填充部分)即8,是short所占字节的整数倍,满足准则(2)。

此时结构体大小为(1+3+4+2)=10(红色为填充部分),不是最宽基本类型float的整数倍,这时,末尾必须添加末尾填充字节2,即(1+3+4+2 +2)=10(红色为填充部分)。

所以最后总大小为12;

总结:分析时只要这样即可:
对于A:1 1  2 4 (红色为填充部分)
对于B:1 3  4 2 2(红色为填充部分)
这样就可以直观的得到结构体大小。
迁移eg:struct{float f; int I; short s;}C; 则sizeof(C)=?(答案:12)


知识扩展1:若出现结构体嵌套,则准则(2)、(3)应改为:

(2),复合成员相对于结构体首地址的偏移量是复合成员中最宽基本类型成员大小的整数倍。
(3),结构体总大小为结构体最宽基本类型成员大小整数倍。
eg:
struct
{
	float f; 
	char c; 
	double d; 
	struct
	{
		double d1;
		float f1;
		double d2;
		char c1;
	}A;
}B;
则sizeof(B)=?

解:先计算A大小:8  4  4  8    1    7(红色为填充部分),得到为32;

所以对于B,排列:4     1    3     8    32(红色为填充部分);

此时成员d的offset=8,前面填充3字节,满足准则2;

A的offset=16,是A中最宽基本类型double所占字节数(8)的整数倍,满足扩展准则2;

此时B大小为48,是B中最宽基本类型double的整数倍,满足扩展准则3.

所以最后sizeof(B)=48;

知识扩展2,若结构体内部出现数组,则准则2应为:

(2),数组相对于结构体首地址的offset是该数组成员大小的整数倍。

eg :struct {double d[2];char*c;}C; 则sizeof(C)=?

解:double大小为8字节,所以double[2]为16;而指针大小均为4,
所以C可排列为:
16 4 4 (红色为填充部分)
得到sizeof(C)=24;

eg:struct {char*c; double d[2];}L;则sizeof(L)=?

解:char* c的大小为4,offset为0;double d[2]的大小为16,offset为double长度8的倍数,这里即取8;结构体总大小也是double长度8的整数倍。
所以L可排列为:
4 4 16 (红色为填充部分)
得到sizeof(L) = 24;

对于共用体:

原则上,共用体大小取决于占据最多内存的成员的长度。但字节对齐准则(3)仍然成立。eg:

union
{
        char c;
        double d;
}e;
则sizeof(e)=8;
union U
{
        int a[5]; //20个字节
        char b;//1个字节
        double c;//8个字节
};
则sizeof(union U) = 24;



内容概要:本文档详细介绍了Analog Devices公司生产的AD8436真均方根-直流(RMS-to-DC)转换器的技术细节及其应用场景。AD8436由三个独立模块构成:轨到轨FET输入放大器、高动态范围均方根计算内核和精密轨到轨输出放大器。该器件不仅体积小巧、功耗低,而且具有广泛的输入电压范围和快速响应特性。文档涵盖了AD8436的工作原理、配置选项、外部组件选择(如电容)、增益调节、单电源供电、电流互感器配置、接地故障检测、三相电源监测等方面的内容。此外,还特别强调了PCB设计注意事项和误差源分析,旨在帮助工程师更好地理解和应用这款高性能的RMS-DC转换器。 适合人群:从事模拟电路设计的专业工程师和技术人员,尤其是那些需要精确测量交流电信号均方根值的应用开发者。 使用场景及目标:①用于工业自动化、医疗设备、电力监控等领域,实现对交流电压或电流的精准测量;②适用于手持式数字万用表及其他便携式仪器仪表,提供高效的单电源解决方案;③在电流互感器配置中,用于检测微小的电流变化,保障电气安全;④应用于三相电力系统监控,优化建立时间和转换精度。 其他说明:为了确保最佳性能,文档推荐使用高质量的电容器件,并给出了详细的PCB布局指导。同时提醒用户关注电介质吸收和泄漏电流等因素对测量准确性的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值