C和C ++中的全局变量有什么区别? [英] What is the difference between the global variables in C and C++?

查看:175
本文介绍了C和C ++中的全局变量有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我测试了以下代码:



在文件 ac / a.cpp中

  int a; 

在文件中 bc / b.cpp

  int a; 
int main(){return 0; }

当我使用 gcc * .c -o test ,它成功了。



但是,当我使用 g ++ * .c -o test 编译源文件时,它失败:

  ccIJdJPe.o:b.cpp :( .bss + 0x0):'a'的多重定义
ccOSsV4n.o:a .cpp :( .bss + 0x0):首先在这里定义
collect2.exe:错误:ld返回1退出状态

我对此很困惑。在C和C ++中的全局变量之间是否有区别?解析方案

这里是标准的相关部分。

§6.9.2/ 2外部对象定义




具有文件范围且没有初始值设定项且没有存储级说明符或存储类说明符为静态的对象的标识符声明构成暂定义。如果翻译单元包含标识符的一个或多个试验性定义,并且翻译单元不包含该标识符的外部定义,那么行为就好像翻译单元包含该标识符的文件范围声明一样,复合类型为




ISO C99§6.9/ 5外部定义

在翻译单元末尾,初始值等于0。


外部定义是一个外部声明,它也是一个函数(除了内联定义)或对象的定义。如果在表达式中使用用外部链接声明的标识符(除了作为sizeof运算符的操作数的一部分,其结果是一个整型常量),则在整个程序中的某处应该只有一个标识符的外部定义;


在C版本中,'g'全局变量被'合并'为一个,所以你只会在一天结束时声明两次。这是可以的,因为不需要extern的时候,或者没有退出。因此,这是出于历史和兼容性原因构建旧代码。这是一个 gcc扩展



它基本上使gcc为名称为'a'的变量分配内存,所以在那里可以有多个声明,但只有一个定义。这就是为什么即使使用gcc,下面的代码也不行。



这也被称为暂定义。 C ++没有这样的事情,而且它正在编译。 C ++没有临时声明的概念。


暂时的定义是没有存储类说明符和没有初始化的任何外部数据声明。如果到达翻译单元的末尾并且没有定义出现与标识符的初始化程序,那么试探性定义就变成完全定义。在这种情况下,编译器会为定义的对象保留未初始化的空间。


请注意,即使使用gcc,以下代码也不会编译,因为这是试验性的定义/声明已经赋值:



在文件ac / a.cpp中

  int a = 1; 

在档案「bc / b.cpp」中

  int a = 2; 
int main(){return 0; }

让我们继续进一步的例子。以下声明显示了正常的定义和暂定义。请注意,静态会使它有点不同,因为这是文件范围,并且不再是外部的。

  int i1 = 10 ; / *定义,外部链接* / 
static int i2 = 20; / *定义,内部联动* /
extern int i3 = 30; / *定义,外部链接* /
int i4; / *暂定义,外部链接* /
static int i5; / *暂定义,内部联系* /

int i1; / *有效的暂定义* /
int i2; / *不合法,与之前的链接不一致* /
int i3; / *有效的暂定义* /
int i4; / *有效的暂定义* /
int i5; / *不合法,与之前的链接不一致* /

更多详细信息可以在以下页面查看: / p>

http://c0x.coding-guidelines.com/ 6.9.2.html



更多详细信息,请参阅此博客帖子:

http://ninjalj.blogspot.co.uk/2011/10/tentative-definitions- in-c.html


I have tested the following code:

in file a.c/a.cpp

int a;

in file b.c/b.cpp

int a;
int main() { return 0; }

When I compile the source files with gcc *.c -o test, it succeeds.

But when I compile the source files with g++ *.c -o test, it fails:

ccIJdJPe.o:b.cpp:(.bss+0x0): multiple definition of 'a'
ccOSsV4n.o:a.cpp:(.bss+0x0): first defined here
collect2.exe: error: ld returned 1 exit status

I'm really confused about this. Is there any difference between the global variables in C and C++?

解决方案

Here are the relevant parts of the standard. See my explanation below the standard text:

§6.9.2/2 External object definitions

A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class specifier static, constitutes a tentative definition. If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0.

ISO C99 §6.9/5 External definitions

An external definition is an external declaration that is also a definition of a function (other than an inline definition) or an object. If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one.

With the C version, the 'g' global variables are 'merged' into one, so you will only have one in the end of the day which is declared twice. This is OK due to the time when extern was not needed, or perhaps did not exits. Hence, this is for historical and compatibility reason to build old code. This is a gcc extension for this legacy feature.

It basically makes gcc allocate memory for a variable with the name 'a', so there can be more than one declarations, but only one definition. That is why the code below will not work even with gcc.

This is also called tentative definition. There is no such a thing with C++, and that is while it compiles. C++ has no concept of tentative declaration.

A tentative definition is any external data declaration that has no storage class specifier and no initializer. A tentative definition becomes a full definition if the end of the translation unit is reached and no definition has appeared with an initializer for the identifier. In this situation, the compiler reserves uninitialized space for the object defined.

Note however that the following code will not compile even with gcc because this is tentative definition/declaration anymore with values assigned:

in file "a.c/a.cpp"

int a = 1;

in file "b.c/b.cpp"

int a = 2;
int main() { return 0; }

Let us go even beyond this with further examples. The following statements show normal definitions and tentative definitions. Note, static would make it a bit difference since that is file scope, and would not be external anymore.

int i1 = 10;         /* definition, external linkage */
static int i2 = 20;  /* definition, internal linkage */
extern int i3 = 30;  /* definition, external linkage */
int i4;              /* tentative definition, external linkage */
static int i5;       /* tentative definition, internal linkage */

int i1;              /* valid tentative definition */
int i2;              /* not legal, linkage disagreement with previous */
int i3;              /* valid tentative definition */
int i4;              /* valid tentative definition */
int i5;              /* not legal, linkage disagreement with previous */

Further details can be on the following page:

http://c0x.coding-guidelines.com/6.9.2.html

See also this blog post for further details:

http://ninjalj.blogspot.co.uk/2011/10/tentative-definitions-in-c.html

这篇关于C和C ++中的全局变量有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆