首先,這是一篇科普文,所以 比較雜,我盡量寫清楚一些。
1、ansi c標準是什麼?gnu又是什麼?ld是什麼?
ansi c是c語言的標準規範,是國際標準化組織制定的國際標準。
雖然 ansi c規範了c語言的實現,但是在實際情況中,各家c語言提供商都會根據平台的不同情況對ansi c進行一定的擴充套件。因此可以將現實中c語言實現看作是ansi c的乙個超集。比較有代表性的例子是linux的gcc編譯器。由於該編譯器對ansi c進行了非常多的擴充套件,linux核心原始碼基本上只能在gcc上面 進行編譯,希望通過其他的編譯器來編譯linux核心幾乎是不可能的。
gnu計畫,又稱革奴計畫。它的目標是建立一套完全自由的作業系統。2023年,gnu計畫已經開發出的軟體包括了乙個功能強大的文字編輯器emacs 。gcc(gnu compiler collection,gnu編譯器集合),是一套由 gnu 開發的程式語言編譯器。
gnu工具鏈包括了構建linux開發環境所需的編譯、鏈結、除錯、軟體工程等工具。gcc(編譯器)、gdb(偵錯程式)、make(軟體等工程工具)。gcc下包括gcc,g++工具。gnu binutils是一組二進位制工具程式集,是輔助gcc的主要軟體,包括我們熟悉的as(gnu彙編器),ar(建立、修改、提取歸檔檔案,歸檔檔案是包含多個檔案內容的乙個大檔案)、ld(聯結器,把目標檔案和歸檔檔案結合在一起),我們在寫程式的時候,有時候報錯:[error] ld returned 1 exit status,這就是程式在鏈結的時候出錯了。
2、c語言可以在不同的原始檔中定義相同名字的全域性變數嗎?
不使用static的時候,兩個不同的原始檔都可以正常編譯,但會出現鏈結錯誤,原因是有兩個地方存在相同的變數,導致編譯器無法識別應該使用哪乙個。
關於全域性變數的幾點說明:
①預設情況下,c語言中的全域性變數和函式的作用域僅限於定義和宣告這個函式或變數的內部,如果需要從這個c檔案之外訪問這些函式或者全域性變數就需要使用 extern關鍵字進行宣告,這是因為c編譯器是以c檔案為單位進行編譯的,如果這個c檔案中引用了其他檔案中定義的函式或者變數,編譯器將無法找到這個函式或者變數的定義,從而給出該函式或者變數未定義的錯誤資訊。
②static關鍵字用於全域性變數的宣告時,作用類似於函式的情況,這個全域性變數的作用域將侷限在宣告該變數的c檔案內部,這個c檔案之外的**將無法訪問這個變數。編譯的時候將會出現類似undeference to "***"的報錯,它是找不到***的,因為使用static相當於進行了檔案隔離。
3、那麼再引申另乙個問題,能不能在
標頭檔案中定義全域性變數?
因為變數只能被定義一次,包含了標頭檔案的原始檔,都將會定義同樣的全域性變數,造成衝突,所以,標頭檔案中不能定義全域性變數。還有網友從節省記憶體的角度來分析,還得到了很多贊,我覺得解釋的不對啊!詳見c語言 中 為什麼不將全域性變數的定義放在標頭檔案中
4、本部落格的導火索,
就是因為在乙個大的工程中,需要增加乙個全域性變數,一開始我是加在了某乙個標頭檔案中,然後報重複定義的錯誤,很顯然,就是因為第2點中說的,由於這個標頭檔案被多個原始檔include,雖然在編譯階段可能能通過,但是在鏈結的時候就會出現重複定義的錯誤。
解決辦法:
①處於盡可能的改動較少的檔案的檔案的原則,自己寫乙個頭問價,檔案內容就一條:全域性變數的定義。這樣的話,在需要使用的位置通過include這個標頭檔案就可以了。但是,如果有多個原始檔需要使用使用這個變數的話,這種情況也會發生重複定義的錯誤,因為include的過程就是複製的過程,那麼很顯然了,這個標頭檔案被拷貝到了多個原始檔中,鏈結時肯定會出現重複定義的錯誤啊。
而且,假設只有乙個原始檔需要這個全域性變數,那麼直接在這個原始檔中定義全域性變數就好了啊!還定義什麼鬼頭檔案哦!
②假設工程中的多個原始檔需要這個全域性變數,那麼你就任找乙個原始檔,把這個全域性變數定義到這個原始檔中,然後新建乙個標頭檔案,在裡面進行extern 這個變數的宣告,最後在需要使用這個全域性變數的原始檔中include你新建的標頭檔案就ok了。
參考:[1] 嵌入式系統高階c語言程式設計,凌明編著,第一章概述
[2] c語言可以在不同的原始檔中定義相同名字的全域性變數嗎
全域性變數在標頭檔案中「定義」
看著標題,定義上面加了乙個引號,這個得注意了。怎麼解釋呢,一般而言,變數只能定義在.c檔案中,宣告變數才在.h檔案中。下面就打破常規,把定義變數的語句放在.h檔案中,但是對實際而言,變數定義在標頭檔案中是表面上的。下面直接給出 有三個檔案a.h a.c main.c a.h裡面的 csharp vi...
全域性變數不能放在標頭檔案其中
看網上各種說法說 變數的宣告和變數的定義,可是還是沒有講清楚什麼是宣告什麼是定義,假設說定義要分配記憶體。宣告不分配。這個誰都知道。剛我在vs2012中測試。按理說 int i。僅僅是宣告吧 可是我在乙個標頭檔案其中宣告 int i 然後兩個cpp檔案都呼叫這個.c檔案,出現了重定義錯誤。我改為 i...
關於標頭檔案中定義的全域性變數的包含
在標頭檔案中定義了乙個變數,若另乙個檔案包含此檔案則會再產生乙個相同變數的定義,在linux環境中編譯時會發生如 menu.o sbss 0x0 multiple definition of is refresh living time thread created main.o sbss 0x0 ...