数据对齐的几问

csapp上说了几个原则, 但我还有不清楚的地方. 网上搜了一个多小时(浪费时间), 也没得到满意的回答, 我想, 验证一下不就完事了?

只有struct需要对齐么? 其它数据类型就不需要么?

先说结论, 并不是.

无论是global还是stack还是heap.

# include <stdio.h>

int main() {
    char a;
    printf("char1:%p
", &a);
    short b;
    printf("short:%p
", &b);
    char e;
    printf("char2:%p
", &e);
    int c;
    printf("int:%p
", &c);
    long d;
    printf("long:%p
", &d);
}

得到的结果是:

char1:0x7ffee42335af
short:0x7ffee42335ac
char2:0x7ffee42335ab
int:0x7ffee42335a4
long:0x7ffee4233598

int和long都能看出来, 为了对齐是做了padding的.

顺便这也能看出真是顺序执行的, 申请了上一个才会申请下一个. 后面看到全局就不是这样的.

也能看出来栈的确是向下增长的.

全局空间
# include <stdio.h>

char a;
short b;
char e;
int c;
long d;

int main() {
    printf("char1:%p
", &a);
    printf("short:%p
", &b);
    printf("char2:%p
", &e);
    printf("int:%p
", &c);
    printf("long:%p
", &d);
}
char1:0x1014af010
short:0x1014af012
char2:0x1014af020
int:0x1014af014
long:0x1014af018

同样是对齐的. 不过与栈不一样, char2的地址最大, 说明分配得很聪明.

# include <stdio.h>
# include <stdlib.h>

int main() {
  char* a = (char*)malloc(1);
  short* b = (short*)malloc(2);
  char* e=(char*)malloc(1);
  int* c=(int*)malloc(4);
  long* d=(long*)malloc(8);
  printf("char1:%p
", a);
  printf("short:%p
", b);
  printf("char2:%p
", e);
  printf("int:%p
", c);
  printf("long:%p
", d);
}

char1:0x7fec06c05860
short:0x7fec06c05870
char2:0x7fec06c05880
int:0x7fec06c05890
long:0x7fec06c058a0

这里用malloc分配, 事实上, 用malloc分配的不仅仅是数据类型的倍数, 它会是16的倍数, 这与SSE有关(SSE我不清楚), 来自csapp 3.9.3. 因此我们才会看到, 都是0结尾的.

struct的指针如果不是数组, 需要对齐么?

# include <stdio.h>

struct stu {
  long a;
  short b;
};

int main() {
  struct stu a;
  struct stu* p = &a;
  printf("size:%lu
pt:%p", sizeof(a), p);
}

根据csapp 3.9.3的解释, 我猜测struct的size是最大类型的倍数, 首地址亦如此.

size:16
pt:0x7ffeead725a0

size证实了我的猜测, 首地址的猜测很可能也对, 但是目前不知道重复验证的办法. 希望看官能为我补充

为什么需要对齐?

不知道, 没仔细看. 有好几种说法. 一种说是cpu只能4个字节一组读取. 不知道有没有出处.

一种说法是cache之类的, 我对cache不熟不知道.

原文地址:https://www.cnblogs.com/Tokubara/p/13857302.html