本文共 2108 字,大约阅读时间需要 7 分钟。
86234 想了解机器、数据类型、内存对齐与内存分布相关的知识点?在这里我将为你详细解答每一个概念。
在不同机器上,编译器处理基础类型占用内存字节不尽相同。通常的系统环境下的数据类型如下表所示:
基础类型 | LP32 | ILP32 |
---|---|---|
char | 1 | 1 |
short | 2 | 2 |
int | 4 | 4 |
long | 4或8 | 8 |
float | 4 | 4 |
double | 8 | 8 |
需要注意的是,实际项目中可以直接使用操作符 sizeof
来确定数据类型的大小。
CPU 并非按字节为单位访问内存,而是按n(n > 1)个字节为整体访问。32位或64位的CPU都会以固定字节为单位进行内存访问。
假设要访问一个4字节的 int
类型变量,当 int
类型数据放在奇数地址时,会占用到下一个4字节的地址区间。这样 CPU 避免了两次访问内存,提高了效率。
内存对齐是编译器的默认行为,但在实际使用中需谨慎对齐,否则可能影响数据正确性。
联合体也是称为 共用体,其大小不是所有成员的总和,而是满足以下条件的最小值:
union u{ int i; char c;};
此联合体大小为 4字节,而不是 5字节。
union u{ int i; char c[10];};
最宽基础类型成员为 int
(4字节),因此联合体大小为 12字节(4 × 3)。
我们需确保结构体成员的起始地址满足以下条件:
#includeunion u{ char u_c1; int u_i1;};struct A{ char c1; short s1; int i1; char c2; char *pc1; union u u1;};struct B{ char c1; short s1; char c2; int i1; char *pc1; union u u1;};struct C{ char c1; char c2; short s1; int i1; char *pc1; union u u1;};int main() { struct A a; struct B b; struct C c; printf("sizeof a : %lu\n", sizeof(a)); printf("a.c1 addr: %p\n", &a.c1); // ... 其他地址输出 return 0;}
输出结果显示,虽然 struct A
和 struct B
成员相同,但内存对齐导致结构体大小不同。
struct D{ char c1; short s1; double d1; char c2;};struct E{ char ch1; char ch2[2]; char ch3[3];};
struct D
以 double
(8字节)为对齐值,总大小为24字节;struct E
将 ch1
、ch2
和 ch3
转换为按字节对齐。
struct F{ int i1; double d1;};struct G{ char c1; struct F f1;};
struct F
内部以 double
为对齐值,大小为16字节。struct G
以 double
为对齐值,总大小为24字节。
#pragma pack
我们可以自定义内存对齐值:
#pragma pack(push)#pragma pack(4)struct H{ char c1; short s1; double d1; char c2;};#pragma pop
通过#pragma pack
调整对齐值,以满足特定需求。
在C语言中,可以使用位域来定义独立的位:
struct I{ int i1:3; int i2:4; int i3:5;};
struct I
总大小为4字节,位域用于低级编程和按位操作。
以上内容涵盖了内存对齐、数据类型大小、联合体、结构体以及自定义对齐等核心内容。理解这些知识点是掌握C语言内存管理的基础。
转载地址:http://axnzk.baihongyu.com/