extern关键字用法

时间:2011-07-28 06:47:36

标签: c++ keyword extern

我有三个程序,我使用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();
}

9 个答案:

答案 0 :(得分:10)

示例2 :您尝试使用两个不同的值初始化全局变量两次。这是错误。

示例3 :首先声明一个extern变量,然后在同一个编译单元中定义一个具有相同名称的变量。这可能。

答案 1 :(得分:7)

您应该使用**extern**关键字,以便引用超出当前范围的内容。

您还应该遵循适用于每个编译器的规则,而不是尝试使用某些编译器的异常,您的示例在我自己的编译器中给了我很多错误。

规则是:

  1. 使用extern引用而不是定义变量。

  2. 使用某种约定进行外部命名。我把所有的外部都当作首都,所以当我看到像MYVAR这样的东西时,我知道它是一个全球性的。

  3. 将所有外部文件放在include标头(.h)文件中并在cpp文件中执行#include,这样更方便,有助于整理源代码。


  4. 请参阅此示例,其中我使用了所有3条规则:

    我的 module1.cpp 文件:

    unsigned short int AGLOBAL = 10; // definer and initializer
    
    void MyFunc(void)
    {
      AGLOBAL+=1; // no need to include anything here cause is defined above
      // more .....    
    }
    

    我的页眉文件 globals.h:

    // this is to include only once
    #ifndef MYH
    #define MYH
    extern unsigned short int AGLOBAL; // no value in here!
    
    #endif
    

    其他 module2.cpp 文件:

    #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:你有一个强烈的声明,然后是一个弱的声明。我真的不确定为什么这个失败了。如果我猜测我会说第二个声明被链接器视为强大。