我有三个程序,我使用extern
个关键字。我无法理解结果。以下是三个例子:
示例1:我期望下面的代码会给出k
的多个声明的编译错误。但它运作正常吗?
int k; //works fine
extern int k = 10;
void main()
{
cout<<k<<endl;
getchar();
}
示例2:当我尝试初始化&#34; k&#34;在上面的例子中编译器给出了错为什么呢?
int k = 20; //error
extern int k = 10;
void main()
{
cout<<k<<endl;
getchar();
}
示例3:在此示例中,我更改了示例1中提到的定义的顺序。当我编译此代码时,我收到错误。为什么呢?
extern int k = 10;
int k; //error
void main()
{
cout<<k<<endl;
getchar();
}
答案 0 :(得分:10)
示例2 :您尝试使用两个不同的值初始化全局变量两次。这是错误。
示例3 :首先声明一个extern
变量,然后在同一个编译单元中定义一个具有相同名称的变量。这不可能。
答案 1 :(得分:7)
您应该使用**extern**
关键字,以便引用超出当前范围的内容。
您还应该遵循适用于每个编译器的规则,而不是尝试使用某些编译器的异常,您的示例在我自己的编译器中给了我很多错误。
使用extern
引用而不是定义变量。
使用某种约定进行外部命名。我把所有的外部都当作首都,所以当我看到像MYVAR
这样的东西时,我知道它是一个全球性的。
将所有外部文件放在include标头(.h)文件中并在cpp文件中执行#include
,这样更方便,有助于整理源代码。
请参阅此示例,其中我使用了所有3条规则:
unsigned short int AGLOBAL = 10; // definer and initializer
void MyFunc(void)
{
AGLOBAL+=1; // no need to include anything here cause is defined above
// more .....
}
// this is to include only once
#ifndef MYH
#define MYH
extern unsigned short int AGLOBAL; // no value in here!
#endif
#include globals.h
char SomeOtherFunc(void)
{
AGLOBAL+=10; // ok cause its declared by globals.h
// do more....
}
答案 2 :(得分:6)
extern
关键字的使用是告诉编译器:
变量在外部定义。
第一个程序应该给你一个错误。你使用的是哪个编译器? BTW,void main()
不标准。无论是在C还是在C ++中。
答案 3 :(得分:5)
你的编译器很草率。编译这个微不足道的变化(包括标题和using
声明),我得到:
$ cat xxx.cpp
#include <iostream>
using namespace std;
int k; //works fine
extern int k = 10;
void main()
{
cout<<k<<endl;
getchar();
}
$ g++ -c xxx.cpp
xxx.cpp:5:12: warning: ‘k’ initialized and declared ‘extern’ [enabled by default]
xxx.cpp:5:12: error: redefinition of ‘int k’
xxx.cpp:4:5: error: ‘int k’ previously declared here
xxx.cpp:7:11: error: ‘::main’ must return ‘int’
$ g++ --version
g++ (GCC) 4.6.0
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$
您使用的是哪种编译器?
答案 4 :(得分:2)
int k;
extern int k = 10;
这在C中是可以的,除了真实的定义之外,你可以有一个“暂定的定义”。在C ++中,它是不允许的。在那里尝试两次声明相同的变量。
My C编译器还警告我同时拥有extern
和初始化是不寻常的。
int k = 20; //error
extern int k = 10;
这会尝试给k
两个不同的值,这当然不起作用。
extern int k = 10;
int k; //error
这似乎与案例1相同。它在C ++中是不允许的,但在C99中似乎是可以接受的。
答案 5 :(得分:2)
案例1:提供 Redefinition Error in c++(gcc-4.3.4)
案例2:提供 Redefinition Error in c++(gcc-4.3.4)
案例3:提供 Redefinition Error in c++(gcc-4.3.4)
在所有这三种情况下,您尝试使用外部链接定义名为k
的变量,并尝试定义另一个名为k
的变量在同一范围内,这会生成重新定义错误。
<强>参考:强>
C ++标准:3.1声明和定义
3 [Example: all but one of the following are definitions:
int a; // defines a
extern const int c = 1; // defines c
int f(int x) { return x+a; } // defines f and defines x
......
在上面的代码段a
&amp; c
都是定义。
如果你的编译器没有给出所有这三种情况的错误,那么就C ++而言它就会被打破。
答案 6 :(得分:2)
对于第三个,你真的想要这个
extern int k = 10;
extern int k; //okay: this is just a declaration.
// extern int k = 4; re-define is no good.
void main()
{
cout<<k<<endl;
getchar();
}
您只能定义一次变量。不过,您可以随意声明多次。
为了进一步说明,int i;
既是声明又是定义。通常,时间错误被认为是“定义”。对于自动变量,声明和定义都在一个语句中完成。
因此,当我们定义int k;
时,已经分配了名称引用为“k”的内存。因此,当您尝试重新定义链接器时,链接器会抱怨。
int k;
extern int k = 3; // already defined in the previous statement
因此,这也是编译错误
extern int k = 3;
int k; // trying to redefine again - bad
这可能仅适用于C ++。我不熟悉C,因此,我不能说C语言。在C ++中,即使我的解决方案也会抱怨,但不会引起错误。
请评判我并纠正我的错误。我也在学习。
答案 7 :(得分:2)
我理解示例2和3.但是编译示例1的事实是如此奇怪。 gcc永远不会编译这样的代码。
答案 8 :(得分:1)
首先,一个挑选。你在谈论全局变量分辨率。这是链接器的工作,而不是编译器。虽然它没有真正意义,因为所有编译器套件通常也都使用链接器执行。
你应该知道的关于全局变量的是它们有两种:弱和强。由于只能有一个具有给定名称的变量,如果有多个定义,链接器必须确定要使用哪个。如果有多个字符串定义,则会出现错误。如果存在单个强定义,则将其选择为规范定义,并且所有其他定义引用它。如果只有弱定义,那么其中一个会被提升。
变量具有赋值给它的值的任何声明都被认为是强的。此外,如果没有赋值,那么extern
关键字将强制变量引用另一个变量(如果存在的话)(实际上是弱者中最弱的)。
案例1:你有一个弱的声明,然后是一个强烈的声明。这很酷。 案例2:你有两个强有力的声明。错误! 案例3:你有一个强烈的声明,然后是一个弱的声明。我真的不确定为什么这个失败了。如果我猜测我会说第二个声明被链接器视为强大。