数据对齐的几问
csapp上说了几个原则, 但我还有不清楚的地方. 网上搜了一个多小时(浪费时间), 也没得到满意的回答, 我想, 验证一下不就完事了?
只有struct需要对齐么? 其它数据类型就不需要么?
先说结论, 并不是.
无论是global还是stack还是heap.
栈
# include <stdio.h>
int main() {
char a;
printf("char1:%p\n", &a);
short b;
printf("short:%p\n", &b);
char e;
printf("char2:%p\n", &e);
int c;
printf("int:%p\n", &c);
long d;
printf("long:%p\n", &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\n", &a);
printf("short:%p\n", &b);
printf("char2:%p\n", &e);
printf("int:%p\n", &c);
printf("long:%p\n", &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\n", a);
printf("short:%p\n", b);
printf("char2:%p\n", e);
printf("int:%p\n", c);
printf("long:%p\n", 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\npt:%p", sizeof(a), p);
}
根据csapp 3.9.3的解释, 我猜测struct的size是最大类型的倍数, 首地址亦如此.
size:16
pt:0x7ffeead725a0
size证实了我的猜测, 首地址的猜测很可能也对, 但是目前不知道重复验证的办法. 希望看官能为我补充
为什么需要对齐?
不知道, 没仔细看. 有好几种说法. 一种说是cpu只能4个字节一组读取. 不知道有没有出处.
一种说法是cache之类的, 我对cache不熟不知道.