1.頭文件被屢次重複引用會形成的後果:ide
頭文件屢次重複引用:一個頭文件被屢次在源文件中屢次引用。spa
先來看一段代碼:
code
/*Test.h*/ #include <stdio.h> int a = 10;
/*Test.c*/ #include "Test.h" #include "Test.h" int main() { printf("d o o\n"); return 0; }
顯示結果:
orm
出現了錯誤,因爲屢次引入同一頭文件,致使變量重定義,這時,有些人就會說,誰會**到引入兩次頭文件,對哦,那麼看下面這個例子:blog
/*Test.h*/ #include <stdio.h> int a = 10;
/*Test.c*/ #include "Test.h" int a = 20; int main() { printf("a = %d\n", a); return 0; }
這個就頗有可能寫出來了,固然仍是先看一下結果:get
和上面那種狀況如出一轍..編譯器
總結:it
當屢次引用同一頭文件時,會有可能出現變量重定義,致使代碼在編譯時出錯。因此規範的代碼應該避免這種狀況的發生。io
這是在知乎關於這個問題的討論和大牛的一些觀點-------知乎大牛編譯
2.怎樣避免發生這種錯誤
第一種方式:
#ifndef __TEST_H__ #define __TEST_H__ //your code #endif
採用條件編譯的方式,當第一次引入TEST_H時,編譯器會檢測到TEST_H尚未被定義,那麼就會執行下面的內容;當再次引入,就會檢測到已經定義了TEST_H,那麼此時就不會執行下面的內容,這種採用宏定義的處理,能夠頗有效的避免發生這種錯誤。
第二種方式:
#pragma once //your code
這是一種由編譯器提供支持的方式,防止同一文件的二次編譯,這裏的同一文件指的是物理文件(實實在在存在的文件)。
兩種方式的對比:
#ifndef的方式依賴於宏名字不能衝突,這不光能夠保證同一個文件不會被包含屢次,也能保證內容徹底相同的兩個文件不會被不當心同時包含。固然,缺點就是若是不一樣頭文件的宏名不當心相同時,可能就會致使頭文件明明存在,編譯器卻硬說找不到聲明的情況。
#pragma once則由編譯器提供保證:同一個文件不會被包含屢次。注意這裏所說的「同一個文件」是指物理上的一個文件,而不是指內容相同的兩個文件。帶來的好處是,你沒必要再費勁想個宏名了,固然也就不會出現宏名相同引起的奇怪問題。對應的缺點就是若是某個頭文件有多份拷貝,此時就不能保證他們不被重複包含。固然,相比宏名相同引起的「找不到聲明」的問題,重複包含更容易被發現並正。
方式一由語言支持因此移植性好,方式二 能夠避免名字衝突。