因此我在课堂上做了这个练习,当我在主函数中创建两个字符时,我必须分辨出两个地址中哪个更大。
因为局部变量是存放在栈中的,栈从高地址开始,到低地址结束。答案很简单,第一个字符的地址更大。
但后来我写了一个小测试程序:
#include "stdio.h"
int main(void)
{
int a = 3;
int b = 4;
printf("Size a: %lu \n"
"size b: %lu \n",
sizeof(a),
sizeof(b));
printf("Address a: %p \n"
"Address b: %p \n",
(void *)&a,
(void *)&b);
return 0;
}
输出:
Size a: 4
size b: 4
Address a: 0x7fffa1eb8a98
Address b: 0x7fffa1eb8a9c
输出结果具有误导性,第二个字符地址更大。我在大学的计算机上尝试了同样的操作,一切正常。你知道为什么会这样吗?
我在使用 Ubuntu 13.04 64 位。
答案1
我认为我不明白为什么会出现问题,但我认为 GCC 可能与此有关...这是 GCC 和 Clang 之间的比较。
$ gcc -o test.gcc test.c
$ ./test.gcc
Size a: 4
size b: 4
Address a: 0x7fffeef71488
Address b: 0x7fffeef7148c
$ clang++ -o test.clang test.c
$ ./test.clang
Size a: 4
size b: 4
Address a: 0x7fff664573f8
Address b: 0x7fff664573f4
您在 uni 使用的编译器及其版本可能是这里的变量元素。
答案2
Kernighan 和 Ritchie 在他们的书“C 编程语言”中定义的 C 标准没有定义如何将参数传递给函数,也没有定义如何存储局部变量,从而使其由实现定义。
编译器的文档应该会告诉您参数是如何传递的,否则您无法编写汇编代码来链接它。对于局部变量,限制甚至更少,因为这些变量只能在函数内部访问,因此编译器可能决定根本不将变量存储在内存中,而是将其保存在寄存器中。当您询问变量的地址时,编译器被迫将其存储在内存中,但除非您使用指向特定变量的指针,否则不需要这样做。
两个不同的编译器可以做不同的事情。许多编译器选择使用堆栈,但其他编译器会在可能的情况下使用寄存器,即使它们使用堆栈,参数的顺序也取决于实现。
ANSI C 标准没有改变这一点。
简而言之,Ubuntu 不会以错误的顺序存储变量。您在 Ubuntu 中使用的编译器只是以与您在大学中使用的顺序不同的顺序存储它们。两者都没错。它们只是不同而已,编译器文档应该解释其实现方式。
对于大多数人在 Linux 中使用的 gcc,其文档为这里。