2010-01-15 34 views
3

可以說我在main.c中有一些全局變量GLOBAL,但是我的main.c有一個#include「other.h」。但other.h也有全局變量GLOBAL。如何在C中訪問正確的全局變量?

當我在main中編寫GLOBAL時,如何讓編譯器知道我的意思。有沒有可以使用的「this」關鍵字?

+3

變量未在頭文件中定義的一個很好的例子。 :-) – 2010-01-15 01:55:58

+2

你應該總是在.c文件中定義*全局變量(這爲它們分配空間),*在.h文件中使用'extern'聲明它們(這使得它們對其他模塊可見)。 – 2010-01-15 03:09:07

回答

-1

我假設你已經在程序中定義了變量,而不是在使用#define的預處理器中。

如果要引用在main.c中創建的那個,只需鍵入global。要引用頭文件中的內容,請使用關鍵字extern。

儘管說實話,你最好將它們聲明爲兩個獨立的變量名。

+0

我很抱歉,但這並沒有對我產生任何意義。特別是建議使用'extern'來引用「頭文件中的變量」(???) – AnT 2010-01-15 02:50:00

+1

「關鍵字extern表示變量的實際存儲和初始值存儲在其他地方」我一直使用C語言完成全局變量,就像我想引用頭中定義的全局變量一樣,它聲明爲 extern 變量 如果我然後想創建一個變量本地的源文件,我正在寫同名,我只是創建一個新的參考像這樣 變量 爲什麼你想要一個全局變量在你的主要在第一個地方超出了我,但這是要求的。不幸的是,大寫字母提示他們已經#define d,使得這個問題毫無意義 – JimiF 2010-01-15 07:57:01

10

在C程序中不能有兩個具有相同名稱的全局變量。 C可能允許通過規定的規則在同一文件範圍內有多個定義,但無論如何所有定義都將引用相同的變量。所以,顯然你的問題是基於不正確的前提。這裏沒有「哪一個」的問題。您只有一個變量。

例如,你可以有文件範圍的定義的序列用C翻譯單元

int i; 
int i; 
int i; 

這是合法的用C(相對於C++),並且所有這些定義實際定義相同的變量,不是三個不同的變量。當然,如果其中一個變量被定義爲局部變量(如果是這樣,你必須在你的問題中說明它)(順便說一句,爲什麼它叫GLOBAL呢?),那麼它會隱藏名稱在文件範圍(或任何更高範圍)中定義的變量。在這種情況下,無法訪問C中的隱藏名稱。重命名局部變量以避免隱藏全局變量。

「other.h也有變量」的意思不清楚。在這種情況下,「有」意味着什麼?變量在其他.h中定義了?或者只是宣稱?如果它只是被宣佈,那麼它並不真正「擁有」它。如果是定義爲那麼......那麼真正的問題是:爲什麼要在.h文件中定義變量?

+0

GLOBAL是兩個文件中的全局變量,而不是本地變量 – SuperString 2010-01-15 02:23:11

+0

我知道。我的答案中的95%專注於兩種聲明都是* global *的情況。提到一個地方聲明是作爲一個附註。 – AnT 2010-01-15 02:26:14

+0

Andrey,有一種方法可以訪問局部變量(比如說函數作用域) - 在更小的範圍內將其重新聲明爲'extern' – qrdl 2010-01-15 05:50:00

0

每個對象模塊只能有一個定義。第二個,如果具有相同的內容,將被忽略。如果不同,則會導致編譯器錯誤。

+0

從技術上講,該標準需要一個定義。由於Fortran COMMON的定義,附錄J確實認可了這個標準的一個「共同擴展」,這是一個可怕的雙關(或者至少是雙關係)。 – 2010-01-15 01:37:07

0

這可能不是您正在尋找的答案,但您爲什麼不嘗試首先避免這種情況(以及可能(全部)使用全局變量)?

0

首先,如果這首先是個問題,那麼您使用的是糟糕的庫,如果可能的話應該重寫/切換。如果你不能,你可以做這樣的事情:

other.h:

int GLOBAL; 
//...other stuff 

爲主。ç

int GLOBAL; 
#define GLOBAL OTHER_GLOBAL 
#include "other.h" 
#undef GLOBAL 

int main(int argc,char** argv) 
    { 
    printf("%i %i",GLOBAL,OTHER_GLOBAL); 
    getchar(); 
    return 0; 
    } 

但是,如果作爲首都暗示,GLOBAL#define版,這可能無法正常工作。 (但它是值得一試無妨。)

+0

只要將main.c中的'GLOBAL'重命名爲'MY_GLOBAL'或類似的名稱會更容易和更安全?不需要毛茸茸的宏。 – 2010-01-15 03:01:50

5

你實際上並不有兩個變量。只有一個,如果兩個模塊使用相同的名稱聲明相同的全局變量,您將得到編譯器(或鏈接器)錯誤,或者編譯器/鏈接器將決定您是否意味着這是單個變量的冗餘聲明併合並它們。

2

像其他人所說的,避免使用同一個全局變量/函數名。養成用模塊名稱加前綴的習慣。即MODULE1_state,MODULE2_state等

如果一個全局變量,只是要一個源文件內使用,不匹配的頭文件中聲明。請將其聲明在源文件的頂部,並使用static關鍵字。需要使用其他模塊訪問的變量需要使用extern關鍵字在頭文件中聲明。全局功能也是如此。它有助於保持相同的公共/私人紀律你會像C++,Java和C#的面向對象的語言正常使用等

例子:

module.h中中:

#ifndef MODULE_H /* Header guard */ 
#define MODULE_H 

/* Declarations for entities that CAN be accessed by other modules, 
    i.e. "public". */ 
extern int MOD_publicVariable; 
extern void MOD_publicFunction(int arg); 

#endif // MODULE_H 

在的module.c:

/* Definitions for entities that CAN be accessed by other modules, 
    i.e. "public". */ 
int MOD_publicVariable = 42; 
void MOD_publicFunction(int arg) {...} 

/* Declarations for entities that CAN'T be accessed by other modules, 
    i.e. "private". */ 
static double MOD_privateVariable = 12.34; 
static void MOD_privateFunction1(void); 
static void MOD_privateFunction2(void); 

/* Function definitions. */ 
void MOD_privateFunction1(void) { 
    int localVariable; /* This doesn't need the module prefix. */ 
    .... 
} 

void MOD_privateFunction2(void) { 
    .... 
} 

模塊前綴(mod_個)可以直接在模塊的名字命名,也可以使用的縮寫。試驗,你最終會選擇一個你喜歡的會議。始終如此使用前綴模仿OO語言中的類/模塊/名稱空間的概念。

確保你知道與定義聲明之間的區別,和extern與靜態。

這惹惱我,C語言課本和課程忽略或掩蓋了多模塊編程的藝術。

編輯: 我忘了提,你不應該讓一般全局變量提供給其他模塊(即讓他們的「私人」)。如果其他模塊需要訪問該變量,請提供「public」「setter」和/或「getter」函數。

+0

我喜歡你強調頭部中的*聲明*,它只是說這個名字的變量存在,而它的*定義*在module.c中,它實際上爲它分配空間(而哪一個容易混淆的是也是一個聲明)。我認爲這是OP正在絆倒的幾件事情之一。 – 2010-01-15 03:07:17