C语言结构体对齐规则:
-
对齐基准:
- 基本数据类型(如char、int、double等)的对齐基准通常与其大小相同。
- 结构体或联合体的对齐基准与其中最大成员的大小相同。
-
对齐方式:
- 编译器将会按照对齐基准要求结构体的每个成员进行对齐。
- 普通成员的对齐位置必须是其大小的整数倍。
- 结构体的起始地址必须是其对齐基准的整数倍。
- 结构体的整体大小必须是其对齐基准的整数倍。
-
填充字节:
- 如果结构体成员的偏移量不满足对齐要求,编译器会在该成员前插入适当数量的填充字节,以满足对齐要求。
- 填充字节的目的在于提高内存访问的效率和安全性,但也会增加内存消耗。
注明:#pragma pack(N) 每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。
代码示例1.
#include<stdio.h>
typedef struct cat
{
int a[10];
char ch;
float f;
double* p;
};
void main()
{
unsigned int i = 0;
i = sizeof(struct cat);
printf("%u", i);
}
运行结果:
根据结构体成员的类型和对齐规则,计算结构体的大小。具体计算如下:
- 整型数组
a
占用40字节(10个int,每个占4字节)。 - 字符型变量
ch
占用1字节。 - 单精度浮点型变量
f
占用4字节。 - 指针变量
p
占用8字节(在64位系统中)。
考虑到内存对齐:40+1+3+4+8=56;
代码示例2.
#include<stdio.h>
#pragma pack(1)
typedef struct cat
{
int a[10];
char ch;
float f;
double* p;
};
void main()
{
unsigned int i = 0;
i = sizeof(struct cat);
printf("%u", i);
}
运行结果:
根据结构体成员的类型和对齐规则,计算结构体的大小。具体计算如下:
- 整型数组
a
占用40字节(10个int,每个占4字节)。 - 字符型变量
ch
占用1字节。 - 单精度浮点型变量
f
占用4字节。 - 指针变量
p
占用8字节(在64位系统中)。
考虑到内存对齐:40+1+4+8=53;
代码示例3.
#include<stdio.h>
typedef struct cat
{
int a[10];
char ch;
double* p;
float f;
};
void main()
{
unsigned int i = 0;
i = sizeof(struct cat);
printf("%u", i);
}
运行结果:
根据结构体成员的类型和对齐规则,计算结构体的大小。具体计算如下:
- 整型数组
a
占用40字节(10个int,每个占4字节)。 - 字符型变量
ch
占用1字节。 - 指针变量
p
占用8字节(在64位系统中)。 - 单精度浮点型变量
f
占用4字节。
考虑到内存对齐:40+1+3+4+8+4+4=64;
代码示例4.
#include<stdio.h>
#pragma pack(4)
typedef struct cat
{
int a[10];
char ch;
double* p;
float f;
};
void main()
{
unsigned int i = 0;
i = sizeof(struct cat);
printf("%u", i);
}
运行结果:
根据结构体成员的类型和对齐规则,计算结构体的大小。具体计算如下:
- 整型数组
a
占用40字节(10个int,每个占4字节)。 - 字符型变量
ch
占用1字节。 - 指针变量
p
占用8字节(在64位系统中)。 - 单精度浮点型变量
f
占用4字节。
考虑到内存对齐:40+1+3+8+4=56;