1. 程式人生 > >extern 用法,全域性變數與標頭檔案

extern 用法,全域性變數與標頭檔案

用#include可以包含其他標頭檔案中變數、函式的宣告,為什麼還要extern關鍵字,如果我想引用一個全域性變數或 函式a,我只要直接在原始檔中包含#include<xxx.h> (xxx.h包含了a的宣告)不就可以了麼,為什麼還要用extern呢??這個問題一直也是似是而非的困擾著我許多年了,今天上網狠狠查了一下總算小有 所獲了:

標頭檔案

首先說下標頭檔案,其實標頭檔案對計算機而言沒什麼作用,她只是在預編譯時在#include的地方展開一下,沒別的意義了,其實標頭檔案主要是給別人看的。

我做過一個實驗,將標頭檔案的字尾改成xxx.txt,然後在引用該標頭檔案的地方用

#include”xxx.txt”

編譯,連結都很順利的過去了,由此可知,標頭檔案僅僅為閱讀程式碼作用,沒其他的作用了!

不管是C還是C++,你把你的函式,變數或者結構體,類啥的放在你的.c或者.cpp檔案裡。然後編譯成lib,dll,obj,.o等等,然後別人用的時候 最基本的gcc hisfile.cpp yourfile.o|obj|dll|lib 等等。
但對於我們程式設計師而言,他們怎麼知道你的lib,dll…裡面到底有什麼東西?要看你的標頭檔案。你的標頭檔案就是對使用者的說明。函式,引數,各種各樣的介面的說明。
    那既然是說明,那麼標頭檔案裡面放的自然就是關於函式,變數,類的“宣告”了。記著,是“宣告”,不是“定義”。


那麼,我假設大家知道宣告和定義的區別。所以,最好不要傻嘻嘻的在標頭檔案裡定義什麼東西。比如全域性變數:

#ifndef _XX_標頭檔案.H
#define _XX_標頭檔案.H
int A;
#endif

那麼,很糟糕的是,這裡的int A是個全域性變數的定義,所以如果這個標頭檔案被多次引用的話,你的A會被重複定義
顯 然語法上錯了。只不過有了這個#ifndef的條件編譯,所以能保證你的標頭檔案只被引用一次,不過也許還是會岔子,但若多個c檔案包含這個標頭檔案時還是會 出錯的,因為巨集名有效範圍僅限於本c原始檔,所以在這多個c檔案編譯時是不會出錯的,但在連結時就會報錯,說你多處定義了同一個變數,

Linking…
incl2.obj : error LNK2005: “int glb” ([email protected]@3HA) already defined in incl1.obj
Debug/incl.exe : fatal error LNK1169: one or more multiply defined symbols found

注意!!!

extern

這個關鍵字真的比較可惡,在宣告的時候,這個extern居然可以被省略,所以會讓你搞不清楚到底是宣告還是定義,下面分變數和函式兩類來說:

(1)變數

尤其是對於變數來說。
extern int a;//宣告一個全域性變數a
int a; //定義一個全域性變數a

extern int a =0 ;//定義一個全域性變數a 並給初值。
int a =0;//定義一個全域性變數a,並給初值,

第四個 等於 第 三個,都是定義一個可以被外部使用的全域性變數,並給初值。
糊塗了吧,他們看上去可真像。但是定義只能出現在一處。也就是說,不管是int a;還是extern int a=0;還是int a=0;都只能出現一次,而那個extern int a可以出現很多次。

當你要引用一個全域性變數的時候,你就要宣告,extern int a;這時候extern不能省略,因為省略了,就變成int a;這是一個定義,不是宣告。

(2)函式
     函式,函式,對於函式也一樣,也是定義和宣告,定義的時候用extern,說明這個函式是可以被外部引用的,宣告的時候用extern說明這是一個宣告。 但由於函式的定義和宣告是有區別的,定義函式要有函式體,宣告函式沒有函式體,所以函式定義和宣告時都可以將extern省略掉,反正其他檔案也是知道這個函式是在其他地方定義的,所以不加extern也行。兩者如此不同,所以省略了extern也不會有問題。
    比如:

int fun(void)
{
return 0;
}

很好,我們定義了一個全域性函式

int fun(void);
我們對它做了個宣告,然後後面就可以用了
加不加extern都一樣
我們也可以把對fun的宣告 放在一個頭檔案裡,最後變成這樣

int fun(void);//函式宣告,所以省略了extern,完整些是extern int fun(void);

int fun(void)
{
return 0;
}//一個完整的全域性函式定義,因為有函式體,extern同樣被省略了。
然後,一個客戶,一個要使用你的fun的客戶,把這個標頭檔案包含進去,ok,一個全域性的宣告。沒有問題。
但是,對應的,如果是這個客戶要使用全域性變數,那麼要extern 某某變數;不然就成了定義了。

總結下:

對變數而言,如果你想在本原始檔中使用另一個原始檔的變數,就需要在使用前用extern宣告該變數,或者在標頭檔案中用extern宣告該變數;

對函式而言,如果你想在本原始檔中使用另一個原始檔的函式,就需要在使用前用宣告該變數,宣告函式加不加extern都沒關係,所以在標頭檔案中函式可以不用加extern。

相關推薦

extern 用法全域性變數檔案

用#include可以包含其他標頭檔案中變數、函式的宣告,為什麼還要extern關鍵字,如果我想引用一個全域性變數或 函式a,我只要直接在原始檔中包含#include<xxx.h> (xxx.h包含了a的宣告)不就可以了麼,為什麼還要用exter

全域性變數檔案中“定義”

        看著標題,定義上面加了一個引號,這個得注意了。怎麼解釋呢,一般而言,變數只能定義在.c檔案中,宣告變數才在.h檔案中。下面就打破常規,把定義變數的語句放在.h檔案中,但是對實際而言,變數定義在標頭檔案中是表面上的。         下面直接給出程式碼,有三個

extern檔案(*.h)的區別和聯絡

個人認為有一些道理:所以轉過來學習了。 用#include可以包含其他標頭檔案中變數、函式的宣告,為什麼還要extern關鍵字?         如果我想引用一個全域性變數或函式a,我只要直接在原始檔中包含#include<xxx.h> (xxx.h包含

noip的c++檔案操作檔案

看一些人寫這些真的心累 首先標頭檔案。 #include <bits/stdc++.h> using namespace std; 可以用!相信我,親測,說不能用的都不是好老師!其他都不要加,這一條包含了一切。 然後是檔案操作。 freopen(“題

NSIS文字及字串函式檔案介紹

轉自 http://hi.csdn.net/jinglidong 文字函式,顧名思義就是處理字串的函式。使用這些字串函式前,必須先包含標頭檔案WordFunc.nsh。該標頭檔案目前包含如下一些函式:WordFind、WordFind2X、WordFind3X、WordRe

CMake2:版本號配置檔案生成

1.基本測試  最基本的功能就是利用原始碼檔案生成一個可執行程式。 CMakeLists.txt: cmake_minimum_required ( VERSION 3.5) project (T

C語言 makefile檔案檔案的寫法。

makefile 檔案的書寫。 總結下make 執行過程       1)make 在當前目錄下找 "Makefile"或"makefile"的檔案     2)如果找到,則會找檔案中第一個目標檔案(target)。     3)如果 main 命令的執行,依賴後面命令執

檔案中只能宣告變數不能定義變數 而宣告變數必須帶extern為什麼檔案變數的宣告都沒有加

 1.標頭檔案中不可以放變數的定義!一般標頭檔案中只是放變數的宣告,因為標頭檔案要被其他檔案包含#include,如果把定義放在標頭檔案的話,就不能避免多次定義變數。C++不允許多次定義變數,一個程式中對指定變數的定義只有一次,宣告可以無數次。 三個例外:1)值在編譯時

extern 用法全局變量文件(重復定義)

.exe 類型 archive 展開 我想 很大的 不用 color 編程思想 轉自 https://www.cnblogs.com/chengmin/archive/2011/09/26/2192008.html 當你要引用一個全局變量的時候,你就要聲明,extern i

## 標題:指標的值傳遞地址傳遞全域性變數傳遞形參傳遞的區別結果

標題:指標的值傳遞與地址傳遞,全域性變數傳遞,與形參傳遞的區別與結果 1.值傳遞與地址傳遞 下面看著段程式碼:void swap(int a, int b){ int t; t=a; a=b; b=t; } void swap1(int *p1,int *p2){ int t; t=*p

關於字元驅動中的變數巨集檔案等的簡介 module_init module_exit

  ssize_t second_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) { } 這是一個檔案讀函式  ssize_t是signed size_t,size_t是標準C庫中定義的

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

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

c++在檔案中定義全域性變數時需要注意的地方

我們知道,在 C++(但不是在 C 語言)中,const 限定符對預設儲存型別稍有影響。在預設情況下,全域性變數的連結性為外部的,但 const 全域性變數的連結性為內部的。也就是說,在 C++ 看來,全域性 const 定義就像使用了 static 說明符一樣。

C/C++語言在檔案中定義全域性變數

轉載:http://blog.csdn.net/chenqiai0/article/details/8490665 全域性變數可不可以定義在可被多個.C檔案包含的標頭檔案中?為什麼? 可以,在不同的C檔案中以static形式來宣告同名全域性變數。標頭檔案中不可以直接定

vs中CString的用法以及所需的檔案

1、CString型別的標頭檔案 #include <afx.h>2、CString的輸出 CString temp="Hello!"; cout<<(LPCTSTR)temp<<endl;3、CString的用法 CString::Co

js全域性變數區域性變數問題變數提升

1、程式的執行結果為:100  10  100 var a = 10; function test(){ a = 100; console.log(a); console.log(this.a); var a; console.lo

[C語言專案]防止檔案全域性變數重複定義

昨天下午將全域性變數定義在H檔案中導致連結時提示變數在多個obj檔案內重複。 解決辦法如下: 將變數移入C檔案中進行定義,然後在H檔案中加入extern在變數之前。 這樣當其它C檔案引用該全域性變數時就會去連結這個變數符號而不是重新生成。 另附防止H檔案被重複包含的處理方

C語言檔案定義全域性變數問題

正確的作法是在c原始檔中定義一個全域性變數,在標頭檔案中加入全域性變數的宣告,在外部檔案呼叫的時候,包含其標頭檔案,加入全域性變數的宣告(不加也是可以的,最好加上)。 //1.c int a;

在c++檔案中使用static修飾的全域性變數

使用static修飾在標頭檔案中修飾的變數,此時不會產生衝突(用static修飾的全域性變數的作用域為定義的原始檔),在多個原始檔中引用該標頭檔案,等於是在每個原始檔中都定義了該變數一次,而且此變數僅在本原始檔中有效,這樣的使用方式不是本身想要的全域性變數,也浪

能不能在檔案中定義全域性變數

首先,這是一篇科普文,所以 比較雜,我儘量寫清楚一些。 1、ANSI C標準是什麼?GNU又是什麼?ld是什麼? ANSI C是C語言的標準規範,是國際標準化組織制定的國際標準。 雖然 ANSI C規範了C語言的實現,但是在實際情況中,各家C語言提供商都會根據平臺的不