Xiao's Blog

Sep 30, 2025

变量内存对齐

有如下C代码:

1
2
3
4
5
6
7
8
9
10
11
12
int a = 1;
int b = 2;
char c1 = 3;
char c2 = 4;
int main(void)
{
printf("a: %p\n",&a);
printf("b: %p\n",&b);
printf("c1:%p\n",&c1);
printf("c2:%p\n",&c2);
return 0;
}

输出类似这样的地址顺序:

1
2
3
4
c1: 0xaaaac23d1010
c2: 0xaaaac23d1011
a: 0xaaaac23d1014
b: 0xaaaac23d1018

这是为什么呢?

1. 变量分布与对齐

  • char c1char c2 连续存放,占用1字节,地址递增。
  • int aint b 分别占4字节(假设int为4字节),并且一般要求4字节对齐
  • 变量在内存中的排列顺序以及对齐方式由编译器决定,但通常遵循“定义顺序+对齐优化”。

2. 变量排列推测(假设编译器按定义顺序分配)

假设变量以定义顺序排列在全局数据区(静态区):

  1. int b
  2. char c1
  3. char c2
  4. int a

输出顺序说明了变量实际排列:

  • c1 先于 c2,相差1字节(0x1010→0x1011)
  • a 地址比 c2 高3字节(0x1011→0x1014),说明a4字节对齐
  • b 地址比 a高4字节(0x1014→0x1018)

变量内存分布(假设起始地址为0x1010):

变量 地址 占用
c1 0x1010 1字节
c2 0x1011 1字节
[填充] 0x1012-0x1013 2字节(对齐a)
a 0x1014 4字节
b 0x1018 4字节

3. 为什么要填充(Padding)

  • int 需要4字节对齐,否则CPU访问会慢甚至出错。
  • 因此在c2之后,编译器自动填充2字节,使a地址是4的倍数(0x1014)。
  • 同样,b 紧跟在a之后,地址为0x1018。

4. 总结

  • 变量按定义顺序排列(全局变量/静态变量)。
  • char类型紧挨着,int类型由于对齐要求,可能有填充字节。
  • 打印出的地址正好反映了这种内存布局和对齐。
OLDER > < NEWER