【发布时间】:2013-04-13 20:28:35
【问题描述】:
我在 Ubuntu 12.10 x86_64 上使用 gcc 版本 4.7.2。
首先这些是我终端上数据类型的大小:
sizeof(char) = 1
sizeof(short) = 2 sizeof(int) = 4
sizeof(long) = 8 sizeof(long long) = 8
sizeof(float) = 4 sizeof(double) = 8
sizeof(long double) = 16
现在请看一下这段代码sn-p:
int main(void)
{
char c = 'a';
printf("&c = %p\n", &c);
return 0;
}
如果我没记错的话,我们无法预测c 的地址。但是每次这个程序都会给出一些以f结尾的随机十六进制地址。因此,下一个可用位置将以0 结尾的某个十六进制值。
在其他数据类型的情况下,我也观察到了这种模式。对于 int 值,地址是以c 结尾的某个十六进制值。对于 double,它是一些以 8 结尾的随机十六进制值等等。
所以我在这里有 2 个问题。
1) 谁在管理这种内存分配?是 gcc 还是 C 标准?
2) 不管是谁,为什么会这样?为什么变量以这样一种方式存储,即下一个可用内存位置从以 0 结尾的十六进制值开始?有什么具体的好处吗?
现在请看一下这段代码sn-p:
int main(void)
{
double a = 10.2;
int b = 20;
char c = 30;
short d = 40;
printf("&a = %p\n", &a);
printf("&b = %p\n", &b);
printf("&c = %p\n", &c);
printf("&d = %p\n", &d);
return 0;
}
现在我观察到的对我来说是全新的。我认为变量会按照它们声明的顺序存储。但不是!事实并非如此。这是随机运行之一的示例输出:
&a = 0x7fff8686a698
&b = 0x7fff8686a694
&c = 0x7fff8686a691
&d = 0x7fff8686a692
似乎变量按其大小的递增顺序排序,然后它们以相同的排序顺序存储,但保持观察 1。即最后一个变量(最大的)以这样的方式存储,即下一个可用内存位置是以0结尾的十六进制值。
这是我的问题:
3) 谁是幕后黑手?是 gcc 还是 C 标准?
4) 为什么要浪费时间先对变量进行排序然后分配内存,而不是按照“先到先得”的原则直接分配内存?这种排序然后分配内存有什么特别的好处吗?
现在请看一下这段代码sn-p:
int main(void)
{
char array1[] = {1, 2};
int array2[] = {1, 2, 3};
printf("&array1[0] = %p\n", &array1[0]);
printf("&array1[1] = %p\n\n", &array1[1]);
printf("&array2[0] = %p\n", &array2[0]);
printf("&array2[1] = %p\n", &array2[1]);
printf("&array2[2] = %p\n", &array2[2]);
return 0;
}
现在这对我来说也很震惊。我观察到的是,如果elements of an array >= 2 和elements < 2,数组总是存储在一些以“0”结尾的随机十六进制值
然后它在观察 1 之后获取内存位置。
所以这是我的问题:
5) 谁在这个以0 结尾的随机十六进制值存储数组的背后?是 gcc 还是 C 标准?
6) 现在为什么要浪费内存?我的意思是array2 可以在array1 之后立即存储(因此array2 的内存位置将以2 结尾)。但是,array2 不是存储在以0 结尾的下一个十六进制值,从而在其间留下 14 个内存位置。有什么具体的好处吗?
【问题讨论】:
-
没有真正涉及“标准”。它可能取决于所使用的编译器的版本、ABI、内核、运行该程序的环境等。ABI 可能要求堆栈指针是 16 字节对齐的,并且编译器将变量放入“as它希望”。
array2必须是字对齐的(4 字节的倍数),而array1不需要... -
为什么走廊这边的房间号都是偶数?为什么走廊对面的房间号都是奇数?
-
你到底为什么要问?你的问题背后的原因是什么,你为什么真的在乎? (您不应该编写严重依赖其确切原因的程序)。
-
@BasileStarynkevitch - 如果编译器落后于以上 3 个观察结果,那么它这样做肯定是有原因的。我的意思是仔细排序变量然后存储它们或总是以某个以
0结尾的随机十六进制值存储数组真的不是一件随机的事情。必须有一些逻辑。为什么编译器要承受这么多的痛苦?如果您知道,请提及任何具体的好处。 -
@rootkea:我还是不明白你为什么要问这个问题,为什么这对你很重要。这通常是您不关心的细节的一部分。相信编译器和系统,它应该在实践中非常明智地做事。
标签: c arrays variables gcc memory-management