>  科技 频道

Linux C语言: 结构体内存对齐和补齐原理

结构体内存对齐

系统:Linux 64位CenOS 7 GCC编译器

内存对齐的表现

typedef struct {

int a; // 4 bytes

char b[5]; // 5 bytes

double c; // 8 bytes

int d; // 4 bytes

short e; // 2 bytes

}MemAlign;

Sizeof(MemAlign) = 32

单个参数计算总和为23个字节,而整个结构体却是32个字节,这是为什么呢?

为什么要进行内存对齐?

我们大多数人在没有搞清楚CPU是如何读取数据的时候,基本都会认为CPU是一字节一字节读取的,但实际上它是按照块来读取的,块的大小可以为2字节,4字节,8字节,16字节。Linux 64位下默认为8字节。

1、平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常,特别是嵌入式设备。

2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

对齐补齐原则

有点文章给出了很复杂的解释,我总结就这两个

(1)第一个成员首地址从0开始。

(2)第一个成员内存大小必须是对齐字节数的整数倍或被整除。从第二个成员开始累加前面所有成员内存大小必须是对齐字节数的整数倍。

#include

#include

#pragma pack(8) typedef struct { int a; // 4 bytes char b[5]; // 5 bytes double c; // 8 bytes int d; // 4 bytes short e; // 2 bytes }MemAlign; typedef struct { int a; MemAlign ma; char c; } NewAlg; #pragma pack(8) int main(int argc char argv[]) { MemAlign mA; int mlen = sizeof(MemAlign); int al = sizeof(mA.a); int bl = sizeof(mA.b); int cl = sizeof(mA.c); int dl = sizeof(mA.d); int el = sizeof(mA.e); printf("al = %d bl = %d cl = %d dl = %d el = %d sum(%d) sizeof = %d " al bl cl dl el(al bl cl dl el) mlen); printf("a=%x b=%xc=%xd=%xe=%x "mA.a mA.b mA.cmA.d mA.e); memset(mA 0x0 mlen); memset(mA.a 0x1 al); memset(mA.b 0x2 bl); memset(mA.c 0x3 cl); memset(mA.d 0x4 dl); memset(mA.e 0x5 el); char *p = (char *)mA; int i; for(i = 0; i < mlen; i ) { printf("%x " *(p i)); } printf(" "); int nlen = sizeof(NewAlg); printf("nlen = %d " nlen); return 0; }

返回顶部