全局变量实现
当我编写以下程序时:
文件 1:
#include <stdio.h>
int global;
void print_global1() {
printf("%p\n", &global);
}
文件 2:
#include <stdio.h>
char global;
void print_global2() {
printf("%p\n", &global);
}
文件 3:
void print_global1();
void print_global2();
int main()
{
print_global1();
print_global2();
return 0;
}
输出:
$ ./a.out
0x804a01c
0x804a01c
这是我的问题:
- 为什么链接器将“int global”和“char global”实现为同一个全局变量:
- 编译器为什么不抱怨(不是
-Wall -Wextra -ansi
的最小警告...) - 全局变量的大小是如何管理的(int 和 char 的大小不同)
PS:第二个问题是架构/编译器相关,所以让我们采用 gcc 或 Visual C++(对于 C),其 int 大小为 32 位
编辑:这不是 C++ 的问题,而是 C 的问题!
我在 Ubuntu 9.10 上使用 gcc 版本 4.4.1,这是编译控制台输出:
$ ls
global_data1.c global_data2.c global_data.c
$ gcc -Wall -Wextra -ansi global_data*.c
$ ./a.out
0x804a01c
0x804a01c
or
$ gcc -Wall -Wextra -ansi -c global_data*.c
$ gcc -Wall -Wextra -ansi global_data*.o
$ ./a.out
0x804a01c
0x804a01c
When I write the following program:
file 1:
#include <stdio.h>
int global;
void print_global1() {
printf("%p\n", &global);
}
file 2:
#include <stdio.h>
char global;
void print_global2() {
printf("%p\n", &global);
}
file 3:
void print_global1();
void print_global2();
int main()
{
print_global1();
print_global2();
return 0;
}
output:
$ ./a.out
0x804a01c
0x804a01c
Here is my question:
- Why are the linker implementing "int global" and "char global" as the same global variable:
- How come the compiler does not complain (not the smallest warning with
-Wall -Wextra -ansi
...) - How are the size of the global variable managed (the size of int and char are different)
PS: The second question is architecture/compiler related, so lets take the gcc or Visual C++ (for C) with the int size as 32 bits
EDIT: THIS IS NOT A QUESTION FOR C++ BUT for C!
I use gcc version 4.4.1 and on Ubuntu 9.10, Here is the compilation console output:
$ ls
global_data1.c global_data2.c global_data.c
$ gcc -Wall -Wextra -ansi global_data*.c
$ ./a.out
0x804a01c
0x804a01c
or
$ gcc -Wall -Wextra -ansi -c global_data*.c
$ gcc -Wall -Wextra -ansi global_data*.o
$ ./a.out
0x804a01c
0x804a01c
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
gcc
不报告任何错误/警告。但g++
确实如此。编辑:
看起来C允许暂定定义< /strong> 为变量。
在您的情况下,两个全局定义都是暂定的,在这种情况下,将选择链接器看到的第一个定义。
将 file2 更改为:
现在,如果像以前一样编译,则 file1 中的暂定 def 将被忽略。
通过以下方式使两个 def 显式化:
现在两者都不能被忽略,我们会得到多个 def 错误。
gcc
does not report any error/warnings. Butg++
does.EDIT:
Looks like C allows tentative definitions for a variable.
In your case both the global definitions are tentative and in that case the first one seen by the linker is chosen.
Change your file2 to:
Now if you compile like before, the tentative def in file1 will be ignored.
Make both the def explicit by:
now neither can be ignored and we get the multiple def error.
这与 C 中所谓的“暂定定义”有关。首先,如果您在 file1 和 file2 中都分配给
global
,则 C 中会出现错误。这是因为global< /code> 不再是在 file1 和 file2 中临时定义的,它是真正定义的。
来自 C 标准(强调我的):
对于您的情况,“翻译单元”(基本上)是每个源文件。
关于“复合类型”:
有关暂定定义的更多信息,请参阅 这个问题及其答案。
对于您的情况来说,它应该是未定义的行为,因为
global
是在翻译单元的末尾定义的,所以您得到global
的两个定义,更糟糕的是,他们是不同的。看起来默认情况下链接器不会抱怨这一点。GNU ld 有一个名为
--warn-common
的选项,它会针对多个暂定定义向您发出警告(通用符号是暂定定义变量的链接器名称):来自 手册:
This has to do with something called "tentative definition" in C. First, if you assign to
global
in both file1 and file2, you will get an error in C. This is becauseglobal
is not tentatively defined in file1 and file2 anymore, it is really defined.From the C standard (emphasis mine):
For your case, "translation unit" (basically) each source file.
About "composite types":
For more on tentative definitions, see this question and its answers.
It seems like for your case, it should be undefined behavior because
global
is defined at the end of the translation units, so you get two definitions ofglobal
, and what's worse, they are different. Looks like the linker by default doesn't complain about this though.GNU ld has an option called
--warn-common
, which warns you for multiple tentative definitions (common symbol is linker's name for tentatively defined variables):From the manual:
链接器允许有像这样的重复外部数据(尽管我很惊讶不同的类型不会引起问题)。您获得哪一个取决于链接命令行上目标文件的顺序。
The linker allows for having duplicate external data like this (although I'm surprised that the different types don't cause a problem). Which one you get depends upon the order of your object files on your link command line.
你使用的是哪个编译器。什么是平台?使用 g++
,我发现在 C++ 中,不同翻译单元中的变量具有完全相同的工作声明。
Which compiler are you using. What is the platform? With g++ I get
AFAIR, in C++ the variables in different translation units much have the exactly same declaration to work.