簡體   English   中英

具有多個定義的extern關鍵字沒有錯誤

[英]No error with extern keyword while having multiple definitions

我有以下代碼段main.c,下面是文件somefile.h

#include "somefile.h"
extern int var = 10000;

int main()
{

    cout << var << endl;
    return 0;
}

和somefile.h包含

int var;

我的問題是,當我執行此代碼時,它會產生輸出10000,但是為什么這不是重新定義錯誤。 由於我假設extern int var = 10000; 是定義。 同樣現在,如果我為somefile.h中的var分配一些值,則會給我一個錯誤,提示重新定義,這是預期的。 我正在使用VS 2010。

這個問題被標記為C和C ++,但是它們是不同的語言。 我的答案是關於C的。

如果您的代碼在文件范圍內包含int var; /* ... */ int var = 10000;序列int var; /* ... */ int var = 10000; int var; /* ... */ int var = 10000; 那么這在C語言中是合法的

該行int var; 稱為暫定定義 ,有點像函數的前向聲明,只是變量。 如果存在變量的后續定義,則該定義將取代它; 否則暫定定義計數,並且變量將初始化為0

除非您專門使用static關鍵字,否則extern關鍵字沒有任何區別,因為在文件作用域定義的變量無論如何都是extern

但是,如果添加了include s somefile.h的第二個翻譯單元,則該行為是不確定的。 這是因為兩個不同的轉換單元都定義了變量var 您的鏈接器可能會診斷出此問題,但C標准不需要這樣做。

如果在somefile.h中將初始化程序提供給該行,例如int var = 5000; 那么這是編譯器必須診斷的多定義錯誤。

我認為OP不會像他那樣來塑造他的示例,以討論暫定定義。 除了語言律師的知識,對於C和C ++,也許還應該陳述基本思想:

  • 僅當您具有多個“翻譯單元” (即c / cpp文件),這些文件分別編譯然后在單獨的步驟中鏈接在一起時, 所有這些才很重要 (如果使用像VS這樣的IDE,這可能在后台發生)。
  • 您要使變量具有多個單位使用的變量,而無需多個定義。 區別稱為“聲明” (即已知)與“定義” (即,通過創建和初始化存儲來創建變量)。 習俗上的奧斯卡·王爾德(Oscar Wilde) 宣稱 “除了他的天才”,但在書本和談話中對其進行了定義
  • “已知”,即聲明,通常是通過頭文件來進行的。 只是很方便:編譯器本身對標題一無所知,但是會轉換由所有標題和包括它們的源代碼組成的串聯代碼序列。 以完全相同的結果,只需將頭文件復制/粘貼到#include指令所在的c文件中,就不會發生任何魔術。 了解這一點至關重要。
  • 眾所周知,全局聲明的前綴為“ extern”,表示該定義可能是轉換單元的外部(請記住,這里的轉換單元是所有標頭和c文件的串聯)。 沒有給出初始值; 變量在創建時會在其他地方初始化。
    (定義可能與我們將使用的翻譯單元相同。沒關系,extern聲明只是多余的,但必須匹配。)
  • 通常必須在您選擇的ac / cpp文件中一次創建並初始化全局變量,即定義一次。 該定義不屬於頭文件。 這是因為標頭應包含在多個c文件中,這將導致多次嘗試創建同一對象。

我從您的示例創建了一個帶有兩個源文件的微型程序,以演示該想法。 第二個c文件包含將在main.c中使用的函數。 兩個c文件都包含相同的頭文件。 頭文件提供了相互的信息交換:兩個c文件都知道另一個文件提供的資源(變量,函數)。 包括頭文件還可以確保c文件中的定義與其他人看到的聲明匹配。

頭文件本身不會創建任何內容。

somefile.h

// make var known to whoever it may concern: 
extern int var;    // declaration, nothing created

extern int computeHalfVar(); // declare a function

HalfVar.c

// The header contains the declaration of var
// which is defined in main.c
#include "somefile.h"

int computeHalfVar() { return var/2; }

main.c

#include <iostream>

// declares computeHalfVar() which we'll use 
#include "somefile.h" 

using namespace std;

// create and initialize var.
// This is the variable everybody else will use.
// The type must match the declaration in the header.
int var = 10000;   

int main()
{
    cout << var << endl;

    // Use a function defined in a different translation unit.
    // The compiler knows the name and signature from the header we included.
    cout << computeHalfVar() << endl;
    return 0;
}

它不僅是重新定義錯誤。 這是“ C274:'var':重新定義;多次初始化”錯誤。 所以實際上是多次初始化。 如果您查閱Microsoft文檔,它會明確指出:

標識符被多次初始化。

http://msdn.microsoft.com/zh-cn/library/88cc602k%28v=vs.90%29.aspx

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM