繁体   English   中英

extern关键字用法

[英]extern keyword usage

我有三个程序,我使用extern关键字。 我无法理解结果。 以下是三个例子:

示例1:我期望下面的代码会给出多次声明k编译错误。 但它运作正常吗?

int k; //works fine
extern int k = 10;

void main()
{
    cout<<k<<endl;
    getchar();
}

示例2:当我尝试在上面的示例中初始化“k”时,编译器会出错。 为什么?

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();
}

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

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

你应该使用**extern**关键字,它的用途是引用超出当前范围的东西。

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

规则是:

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

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

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


请参阅此示例,其中我使用了所有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....
}

使用extern关键字是告诉编译器:

变量在外部定义。

第一个程序应该给你一个错误。 你使用的是哪个编译器? BTW, void main()不是标准的。 既不是C语言,也不是C ++语言。

你的编译器很草率。 编译这个微不足道的变化(包括标题和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.

$

你使用的是哪个编译器?

int k;
extern int k = 10; 

这在C中是可以的,除了真实的定义之外,你可以有一个“暂定”。 在C ++中,它是不允许的。 在那里尝试两次声明相同的变量。

我的C编译器还警告我,同时进行extern和初始化是不寻常的。

int k = 20; //error
extern int k = 10;    

这试图给k两个不同的值,这当然是行不通的。

extern int k = 10;
int k;   //error 

这似乎与案例1相同。它在C ++中是不允许的,但在C99中似乎是可以接受的。

案例1: 在c ++中给出重新定义错误(gcc-4.3.4)

案例2: 在c ++中给出重新定义错误(gcc-4.3.4)

案例3: 在c ++中给出重新定义错误(gcc-4.3.4)

在所有这三种情况下,您尝试使用外部链接定义名为k的变量,并尝试在同一范围内定义另一个名为k变量,这会生成Redefinition错误。

参考:
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
......

在上面的代码片段中, ac都是定义。

如果你的编译器没有给出所有这三种情况的错误,那么就C ++而言它就会被破坏。

对于第三个,你真的想要这个

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 ++中,即使我的解决方案也会抱怨,但不会对它产生错误。

请评判我并纠正我的错误。 我也在学习。

我理解了示例2和3.但是编译示例1的事实是如此奇怪。 gcc永远不会编译这样的代码。

首先,一个挑选。 你在谈论全局变量分辨率。 这是链接器的工作,而不是编译器。 虽然它没有真正意义,因为所有编译器套件通常也都使用链接器执行。

你应该知道的关于全局变量的是它们有两种:弱和强。 由于只能有一个具有给定名称的变量,如果有多个定义,链接器必须确定要使用哪个。 如果有多个字符串定义,则会出现错误。 如果存在单个强定义,则将其选择为规范定义,并且所有其他定义引用它。 如果只有弱定义,那么其中一个得到提升。

变量具有赋值的任何声明都被认为是强大的。 此外,如果没有赋值,则extern关键字将强制变量引用另一个变量(如果存在的话)(实际上是弱者中最弱的)。

案例1:你有一个弱的声明,然后是一个强烈的声明。 这很酷。 案例2:你有两个强有力的声明。 错误! 案例3:你有一个强烈的声明,然后是一个弱的声明。 我真的不确定为什么这个失败了。 如果我猜测我会说第二个声明被链接器视为强大。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM