所以我试图理解C如何将我的变量存储在内存中,并且在我遇到这个问题之前我一直做得很好:
我编写了以下简单的程序,它告诉我变量逐个存储的位置,这样我就可以知道类型之间的区别,但我无法建立任何链接,这个数字在我相信的同时看起来如此随意它与类型有关。那么,任何线索为什么角色总是得到较低的内存地址,即使它们是最后声明的呢?
int main ()
{
int integer1 = 6;
int integer2 = 2;
int integer3 = 3;
char character1 = 'C';
char character2 = 'B';
char character3 = 'D';
char string1[4] = "Hi!";
char string2[4] = ":D";
char string3[4] = "ack!";
printf ("integer1 : %d, at %p\n", integer1, &integer1);
printf ("integer2 : %d, at %p\n", integer2, &integer2);
printf ("integer3 : %d, at %p\n", integer3, &integer3);
printf ("character1 : %c, at %p\n", character1, &character1);
printf ("character2 : %c, at %p\n", character2, &character2);
printf ("character3 : %c, at %p\n", character3, &character3);
printf ("string1 : %s, at %p\n", string1, string1);
printf ("string2 : %s, at %p\n", string2, string2);
printf ("string3 : %s, at %p\n", string3, string3);
}
输出:
integer1 : 6, at 0x7ffe40915b40
integer2 : 2, at 0x7ffe40915b44
integer3 : 3, at 0x7ffe40915b48
character1 : C, at 0x7ffe40915b3d
character2 : B, at 0x7ffe40915b3e
character3 : D, at 0x7ffe40915b3f
string1 : Hi!, at 0x7ffe40915b4c
string2 : :D, at 0x7ffe40915b50
string3 : ack!, at 0x7ffe40915b54
编辑:编译:GCC 7.3.0
答案 0 :(得分:4)
内存中变量的排序是编译器的实现细节。无法保证它的外观。
话虽如此,似乎编译器试图以这样的方式布置变量,使得所有变量都正确对齐,它们之间没有任何填充,即它是为了节省空间。
答案 1 :(得分:1)
请记住,您正在处理自动变量。没有关于如何实现自动变量的正式规范,但在任何你可能会发现它们将在堆栈中的系统中。
(假设没有优化)
如果查看main()函数的生成代码(通常是-S选项),您可能会找到类似
的语句。 MOV SP, BP
DECL #SOMENUMBER, SP
其中SOMENUMBER是主函数对局部变量所需的字节数。
然后编译器为每个变量分配SP寄存器的偏移量。它看起来像那样:
1(SP) ; is character1
2(SP) ; is character2
3(SP) ; is character3
4(SP) ; is integer1
8(SP) ; is integer2
12(SP) ; is integer3
16(SP) ; is string1
20(SP) ; is string2
24(SP) ; is string3
堆栈通常向下增长,因此较低的变量地址将具有较小的偏移量。
然后编译器需要初始化堆栈上的每个位置。
编译器的分配器将弄清楚如何进行这种映射。您需要查看GCC代码,找出它为什么采用它的路径。
投掷
short short1 ;
long long long1 ;
char str[] = "12345" ;
可能会给你一些有趣的结果,看看不同的大小如何影响分配器。