1. 程式人生 > >fatal error LNK1169: 找到一個或多個多重定義的符號或多個.c/.cpp檔案想同時呼叫定義在.h檔案裡面的全域性變數,防止重定義變數問題。

fatal error LNK1169: 找到一個或多個多重定義的符號或多個.c/.cpp檔案想同時呼叫定義在.h檔案裡面的全域性變數,防止重定義變數問題。

為什麼.h檔案中不能定義全域性變數?

原因: 存在多次建立變數.如果標頭檔案中可以定義全域性變數,那麼每個包含該標頭檔案的檔案裡都會有該全域性變數的定義.因為C語言的include是直接將檔案嵌入到include這個地方的.

解決辦法: ​在標頭檔案使用 extern 來宣告該全域性變數,然後在任意一個.cpp檔案中定義該變數.全域性變數是存放在靜態區的.會被預設初始化為0.

原文:https://blog.csdn.net/jchnlau/article/details/49774599

 

C語言:全域性變數在多個c檔案中公用的方法

用C語言編寫程式的時候,我們經常會遇到這樣一種情況:希望在標頭檔案中定義一個全域性變數,然後包含到兩個不同的c檔案中,希望這個全域性變數能在兩個檔案中共用。

  舉例說明:專案資料夾project下有main.c、common.c和common.h三個檔案,其中common.h檔案分別#include在main.c和common.c檔案中。現在希望宣告一個字元型變數key,在main.c和common.c中公用。如下圖所示:

有人想,既然是想兩個檔案都用,那就在common.h中宣告一個unsigned char key,然後由於包含關係,在main.c和common.c中都是可見的,所以就能共用了。

這種想法其實是很多初學者都會想到的,想起來確實有道理,但是實際寫出來,我們發現編譯的時候編譯器提示出錯,一般提示大概都類似於:Error: L6200E: Symbol key multiply defined (by common.o and main.o). 也就是說編譯器認為我們重複定義了key這個變數。這是因為#include命令就是原封不同的把標頭檔案中的內容搬到#include的位置,所以相當於main.c和common.c中都執行了一次unsigned char key,而C語言中全域性變數是專案內(或者叫工程內)可見的,這樣就造成了一個專案中兩個變數key,編譯器就認為是重複定義。

 

 

  正確的解決辦法:使用extern關鍵字來宣告變數為外部變數。具體說就是在其中一個c檔案中定義一個全域性變數key,然後在另一個要使用key這個變數的c檔案中使用extern關鍵字宣告一次,說明這個變數為外部變數,是在其他的c檔案中定義的全域性變數。請注意我這裡的用詞:定義和宣告。例如在main.c檔案中定義變數key,在common.c檔案中宣告key變數為外部變數,這樣這兩個檔案中就能共享這個變數key了,如下圖所示。

程式碼如下(只寫跟我們所說問題有關的部分):

  (1)main.c檔案

  #include "common.h"
  unsigned char key;

  (2)common.c檔案:

  #include "common.h"
  extern unsigned char key;

  很多人看了可能糊塗,這裡稍微說一下,其實就是變數定義和變數宣告的區別,變數定義使用“資料型別+變數名稱”的形式,編譯器需要給他分配記憶體單元的;而變數宣告使用“extern 變數型別+變數名稱”的形式,是告訴編譯器我這個變數將在其他外部c檔案中定義,我這裡只是在外部用它。編譯器就不給他分配記憶體空間,而等到真正遇到變數定義的時候再給他分配記憶體空間。

  由於很多人從開始學C語言就一直把定義變數叫宣告變數,一開始就叫錯了,所以導致現在分不清定義和宣告的區別。要是還理解不了就想想函式的定義和宣告,函式定義是編寫函式功能實體,編譯器要編譯這個函式並且要分配記憶體空間,而函式宣告並不生成函式功能實體,只是告訴編譯器這是個函式,這個函式在後面將會定義實體,我這裡只是提前用,編譯器就會接著繼續往下編譯,如果子函式寫在main函式之後,那麼宣告是必須的,如果不宣告函式編譯器都不知道這是個函式,編譯就會報錯。

  說了這麼多應該說明白了,如果還有問題可以參考譚浩強的那本C語言書,書中有詳細解釋和例子。

——————————————————————————————————————————

以下部分來源: http://blog.sina.com.cn/s/blog_5e87dc1201018qll.html

  1、普通變數定義成全域性變數
     如果是普通型別,完全可以不用*.h檔案,直接在*.c檔案中定義,在呼叫檔案處用extern 宣告,因為對於普通型別,編譯器是可以識別的。比如在一個 my.c檔案中,我定義了char name[10];那麼在別的檔案中只要用extern char name[](由於是宣告,一位陣列可以省略大小,但不建議用指標,比較指標和陣列是兩回事)外部宣告就可以了,告訴編譯器這個變數我已經定義過了,具體怎樣,你慢慢找吧。這符合常理,因為char是編譯器能自主識別的型別。
      2、自定義結構體型別定義成全域性變數
     不同於普通型別,如果不預先通知編譯器,編譯器是不會識別你自定義的型別的。這個時候,*.h檔案便出現了。不是定義結構型別不佔記憶體嗎?那好,我大結構體的定義放在*.h檔案中,這樣一來,無論你incude無數次,記憶體都不會被佔用的。而且這樣還有個好處,在別的檔案中可以include這個*.h檔案,這樣,在這個檔案中,編譯器就可以識別你的自定義型別了,目的不就達到了?  假如我在global.h中定義了
typedef struct _POSITION
{
        int x;
        int y;
}POSITION;
那麼我可以在一個global.c檔案中實現全域性變數的定義,不過要include那個*.h檔案,比如
 
include “global.h”
POSITION current,;  
這樣就定義了cunrrent這個變數,在別的檔案中引用這個變數時,只要extern POSITION current;進行宣告,然後就可以用了,不過這個檔案也還得include "global.h" 因為如果不包含,在這個檔案中是不識別POSITION型別的。

 

1.如何引用一個已經定義過的全域性變數?   

答:extern  可以用引用標頭檔案的方式,也可以用extern關鍵字,如果用引用標頭檔案方式來引用某個在標頭檔案中宣告的全域性變理,假定你將那個編寫錯了,那麼在編譯期間會報錯,如果你用extern方式引用時,假定你犯了同樣的錯誤,那麼在編譯期間不會報錯,而在連線期間報錯。

2.全域性變數可不可以定義在可被多個.C檔案中?為什麼?   

答:可以,在不同的C檔案中以static形式來宣告同名全域性變數。   可以在不同的C檔案中宣告同名的全域性變數,前提是其中只能有一個C檔案中對此變數賦初值,此時連線不會出錯。

原文:C語言:全域性變數在多個c檔案中公用的方法

 

幾個.C檔案想同時呼叫定義在.H檔案裡面的全域性變數,防止重定義變數問題。

首先,在.H檔案裡面加extern關鍵詞宣告全域性變數,
然後,在.C檔案中定義全域性變數,變數定義不要放在標頭檔案裡。
在C檔案裡定義,在標頭檔案裡extern
例如:

module1.h 
extern int iCounts;//宣告全域性變數

module1.c
int iCounts;
//在任意一個.c或.cpp檔案中定義該全域性變數

#include "moudule1.h"
moudule2.c//其他C檔案,包含.H檔案後(#include "moudule1.h"),可以直接引用全域性變數
Class

{
  
moudule2中的其它程式碼
}
 

 

“error LNK1169: 找到一個或多個多重定義的符號”的解決方法

廢話不多說,下邊舉例子:

 

有三個檔案,分別為a.h、a.cpp、b.cpp。

a.h和a.cpp的關係不多說,一看就明瞭,b.cpp也引用了a.h標頭檔案,編譯時通過,連結時出現“error LNK1169: 找到一個或多個多重定義的符號”的錯誤。也就是說單個檔案是沒有語法錯誤的,連結時出了問題。我在a.h中也加入了#ifndef..#define..#endif的標頭檔案衛士,但是也是不行,查了下資料找到了原因。a.h中的變數在a.cpp和b.cpp中有使用,在編譯時是不會出錯,但是在連結時就會出現重定義的錯誤。解決方法就是在a.h宣告的變數前加上extern的關鍵字,在b.cpp中不加extern關鍵字重新宣告一次,就完美通過。

 

這其實是個很基礎的問題,之所以犯這個錯是因為單純地以一個檔案包含標頭檔案的方式來看待。
原文:https://blog.csdn.net/BartonShan/article/details/54966420

 

C++多個檔案共享同一標頭檔案時全域性變數的宣告

前言

在編寫非小型程式時,僅僅用到函式進行模組化是不夠的,由於函式眾多,在一個或幾個檔案中完成程式會造成單個程式檔案過長。這樣一來,不知不覺中提高的模組間的耦合性,擴大了程式的修改時間。這時候將功能分散到更多的模組中就變得尤為重要了。

那麼,保持一個統一的結構,將不同檔案納入相同的一組檔案中,並可以保持使用便成為了第一個問題。將原來在一個檔案下的變數編寫成不同檔案都可以使用的變數就是我們需要解決的第二個問題。

通過活動前處理器塊來避免重複編譯

在檔案過多的情況下,由於每個程式都會包含自己的標頭檔案,在編譯過程中,很有可能一個頭檔案被包含了多次,這時,進行編譯會發生重複編譯的錯誤。

例如:有兩個子模組標頭檔案:funtion1.h 和funtion2.h
funtion1.h中包含的標頭檔案均是標準標頭檔案,如:iostream, vector 等
funtion2.h中除了標準標頭檔案還包括有:#include “funtion1.h”
這時,有一個檔案包含以上兩個標頭檔案,如:
main.cpp中有如下內容:
:#include < iostream>
:#include “funtion1.h”
:#include “funtion2.h”

由於funtion2.h中已經包含了funtion1.h在main.cpp中,又被包含了一次,這樣就發生了重複編譯的錯誤。由於重複包括標準標頭檔案不會導致這樣的錯誤,所以需要我們對自行編寫的標頭檔案進行特殊說明,如
funtion1.h 中:
:#ifndef H_funtion1
:#define H_funtion1
:#include < fstream>
:#include < iostream>
:#endif
加入是否被編譯的檢查,這樣的話就以避免重複編譯相同的檔案。

多個檔案共享同一變數

多檔案的組織

多個cpp檔案要想納入到同一個組織中,最簡單的方式是,同時包含一個自行編寫的標頭檔案,在這個標頭檔案中宣告各個檔案中要被其他檔案所使用的函式簽名,還有共用的變數。

共用的變數

函式的宣告(不是定義),必須同時滿足兩點不同的要求:

變數型別前面有extern的修飾詞。
沒有初始化,或賦初值。
我們首先要做的就是在這個共用的標頭檔案中宣告各個檔案間要共同使用的變數,如:
TotalHeader.h中

extern int a;
extern int b;

第二步,在其中一個檔案中的全域性位置定義變數,如:
funtion1.cpp中
:#inlcude “TotalHeader.h”
:#include …
int a = 0;
int b = 0;
void fun1(){

}

通過以上兩步就可以實現多個檔案中共享同一標頭檔案時的全域性變數宣告

原文:C++多個檔案共享同一標頭檔案時全域性變數的宣告

 

示例程式:

https://pan.baidu.com/s/1w17xs2W8tMgFc5OGRDvLfg

https://pan.baidu.com/s/1GPwb1FVYDyoEu5mSnAihbQ