我注意到我用C编写的某些程序没有在我的机器上运行,但是它们与其他程序一样。所以为了测试这个,我编写了一个简单的程序来测试堆栈如何推送和弹出局部变量:
#include <stdio.h>
#include <string.h>
int main() {
char char_test[10];
int int_test = 0;
strcpy(char_test, "Hello");
}
然后我调试了这个程序,发现int_test的内存地址比char_test高,即使根据我的知识,第一个声明的局部变量应该有更高的内存地址。然后我添加了两个打印函数,用于打印变量的内存地址:
#include <stdio.h>
#include <string.h>
int main() {
char char_test[10];
int int_test = 0;
strcpy(char_test, "Hello");
printf("Address of char_test: 0x%x\n", &char_test);
printf("Address of int_test: 0x%x\n", &int_test);
}
现在,第一个局部变量的内存地址高于第二个。打印地址会改变变量的顺序吗?我做错了吗?
答案 0 :(得分:2)
您所引用的顺序要求适用于struct
的成员。编译器不需要以某种方式对局部变量进行排序。实际上,没有要求编译器将堆栈用于其自动变量,甚至根本不需要分配它们,如果它可以侥幸逃脱它。
在您的示例中,编译器看起来就是这样:由于未使用int_test
,编译器假装它不存在。一旦你开始使用它的地址,编译器就被迫分配它。碰巧在char_test
之前分配变量,但没有义务这样做。
答案 1 :(得分:2)
内存中变量的排序(无论它们是本地还是全局)都与任何合理的程序无关。
已经错误的程序的行为当然可以取决于变量的相对接近程度(特别是溢出的数组),但这显然是因为程序已经错了。
而且,不,没有规则可以管理,也不保证您的编译器(和链接器)将如何分配地址。
答案 2 :(得分:1)
内存中变量的排序是编译器的实现细节。
它可能将它们按顺序排列,或按相反顺序排列,或按数据类型或其他方式分组。这与一个编译器的不同之处不同,也可能因不同的优化级别而不同。此外,正如您所见,使用哪种策略可能会因看似无关的代码更改而发生变化。
C标准对如何完成此操作没有任何要求,因此您无法依赖其订单。