gcc c 内存对齐的笔记和实验
1. 数据类型
<数据类型>
包括
<基础类型>
<自定义类型>
- <基础类型> 包括
(unsigned) byte
(unsigned) short
(unsigned) int
(unsigned) long
(unsigned) long long
float
double
void *
/* 指针 */<枚举>
<自定义类型>
包括
<结构体>
<联合体>
2. 字节大小
2.1. 查看 <数据类型>
的 字节大小。
用法:
sizeof(type)
3. 地址对齐
3.1. 查看 <数据类型>
的 地址对齐
用法:
__alignof__(type)
3.2. <基础类型>
地址对齐
定义:
__alignof__(<基础类型>)
等于sizeof(<基础类型>)
例子:
====== primary =========
char: align 1, size 1
short: align 2, size 2
int: align 4, size 4
long: align 8, size 8
long long: align 8, size 8
void *: align 8, size 8
enum xxx: align 4, size 4
3.3. <自定义类型>
地址对齐
定义:
__alignof__(<自定义类型>)
等于<自定义类型>
中所有成员变量的__alignof__(<基础类型>)
的最大者。
注意:
- 对于 嵌套 的
<自定义类型>
。则嵌套求解。
例子:
- 成员变量中的
__alignof__
最大者 为 8 (struct A.d
和struct A.e
), - 所以
__alignof__(struct A)
为 8。
struct A{
char a;
int b;
short c;
long d;
long long e;
char f;
};
struct A: align 8, size 40
struct A.a: offset 0, align 1, size 1.
struct A.b: offset 4, align 4, size 4.
struct A.c: offset 8, align 2, size 2.
struct A.d: offset 16, align 8, size 8.
struct A.e: offset 24, align 8, size 8.
struct A.f: offset 32, align 1, size 1.
4. 规则
<自定义类型>
中的<成员变量>
的 偏移地址 为各自__alignof__(<成员变量>)
的整数倍。<自定义类型>
的 偏移地址 和 字节大小 为__alignof__(<自定义类型>)
的整数倍。
注意:
- 以上的两条规则是不会改变的。偏移地址 和 字节大小 仍然保持为
__alignof__
的整数倍。 __attribute__((aligned))
,__attribute__((aligned(n)))
,只会修改__alignof__(<自定义类型>)
的值。- 单独使用
__attribute__((packed))
,#pragma pack(n)
,会修改__alignof__(<自定义类型>)
和__alignof__(<成员变量>)
的值。 - 同时使用
__attribute__((packed))
和__attribute__((aligned(n)))
4.1.__attribute__((packed))
,只会修改__alignof__(<成员变量>)
的值。
4.2.__attribute__((aligned(n)))
,只会修改__alignof__(<自定义类型>)
的值。 - 同时使用
#pragma pack(n)
和__attribute__((aligned(n)))
5.1.#pragma pack(n)
,只会修改__alignof__(<成员变量>)
的值。
5.2.__attribute__((aligned(n)))
,只会修改__alignof__(<自定义类型>)
的值。
5. 设置 <自定义类型>
的 地址对齐
使用 __attribute__((aligned[(n)]))
可以 设置 __alignof__(<自定义类型>)
的 地址对齐。
有 自动 和 用户定义 两种方式。
5.1. 单独使用 自动 地址对齐
- 单独使用
__attribute__((aligned))
,编译器根据最大运行效率的方式对齐。
用法:
struct type{
/* member */
}__attribute__((aligned));
例子:
- 默认
__alignof__(struct A)
为 8。 - 编译器根据最大运行效率的方式对齐 为
__alignof__(struct B)
为 16。
struct B{
char a;
int b;
short c;
long d;
long long e;
char f;
}__attribute__((aligned));
struct B: align 16, size 48
struct B.a: offset 0, align 1, size 1.
struct B.b: offset 4, align 4, size 4.
struct B.c: offset 8, align 2, size 2.
struct B.d: offset 16, align 8, size 8.
struct B.e: offset 24, align 8, size 8.
struct B.f: offset 32, align 1, size 1.
5.2. 单独使用 用户定义 地址对齐
- 使用
__attribute__((aligned(n)))
,编译器按照 用户定义 地址对齐。
1.1. 取n
与 默认的__alignof__(<自定义类型>)
的最大者 来对齐。
用法:
struct type{
/* member */
}__attribute__((aligned(n)));
例子:
- 默认的
__alignof__(struct A)
为 8,而现在用户定义n
为 1。 - 以 最大者 来 8 来对齐。最后
__alignof__(struct C)
为 8。
struct C{
char a;
int b;
short c;
long d;
long long e;
char f;
}__attribute__((aligned(1)));
struct C: align 8, size 40
struct C.a: offset 0, align 1, size 1.
struct C.b: offset 4, align 4, size 4.
struct C.c: offset 8, align 2, size 2.
struct C.d: offset 16, align 8, size 8.
struct C.e: offset 24, align 8, size 8.
struct C.f: offset 32, align 1, size 1.
例子:
- 默认的
__alignof__(struct A)
为 8,而现在用户定义n
为 32。 - 以 最大者 来 32 来对齐。最后
__alignof__(struct E)
为 32。
struct E{
char a;
int b;
short c;
long d;
long long e