標籤:
不知道上篇的例子有沒有朋友去試過,試過的朋友應該很疑惑,為什麼會報錯?
我們來編譯幾個檔案看看標頭檔到底是如何匯入的;
a.c
void hellow(){ printf("hellow"); }
a.h
#include "b.h";void hellow();
b.c
void word(){ printf("word"); }
b.h
void word();
test.c
#inculde <stdio.h>#inculde "a.h"int main(){ hellow(); word(); }
接下來把test.c編譯為先行編譯檔案..gcc -E test.c -o
用記事本開啟檔案,前面代碼先不管拉到最下方
可以看到我們寫的代碼..前面代碼是什麼呢 前面一大坨都是庫檔案<stdio.h>的代碼,所以include匯入檔案可以理解為拷貝檔案進來 往下看
# 1 "testA.h" 1 於是他把testA.h的所有代碼拷貝進來了:
但是拷貝的時候又遇到testA.h內的 # 1 "testB.h" 1 於是把testB.h的所有代碼也考進來就有了下面幾句
# 1 "testB.h" 1
void word();
這時候testA還沒拷貝完繼續拷貝testA的第二行
void hellow(); 當include都拷貝完了才會開始編譯main函數。
在看上一篇的問題A.h包含B.h,B.h又包含A.h。。仔細想想先行編譯時會怎麼樣?
先行編譯到A.h 發現有一行#include "B.h"於是去拷貝B.h,又發現B.h有一行#include"A.h"又去拷貝A.h,造成無限迴圈...
那麼如何解決這種問題呢?
#ifndef name
#define name
標頭檔內容
#endif
ifndef 是"if not defined"的簡寫,是宏定義的一種,它是可以根據是否已經定義了一個變數來進行分支選擇
define 定義一個宏 endif 則是終止if
以下是個人對於標頭檔的一些理解和測試結果
1.當標頭檔引用自身或者相互引用時會出現死迴圈 提示迴圈過於深入
2.當A,B都包含C時編譯可以通過 但先行編譯狀態下可看到 C檔案出現了兩份 程式不會因此不能運行 但拖慢了程式的載入
3.當A,B中擁有重名的方法 並在主函數調用時會出現編譯錯誤(不調用則編譯通過) 未明確定義
4.C程式先行編譯時根據標頭檔尋找目標檔案(*.o),所以目標檔案重新編譯並不影響它所依賴的檔案
5.解決標頭檔匯入重複或迴圈問題
#ifndef _test_h_
#define _test_h_
標頭檔內容
#endif
---------------------------------------------------------------------------------------------------------------------------------
標頭檔就說到這裡..之前有提到宏定義 宏定義是什麼呢
#define A=3; //這是定義一個宏有不少人認為這就是定義一個全域的常量,但是他與常量相似卻又有所不同,他會把代碼中所有A都替換成3但這個操作是在預先處理階段就進行了,
比如你在代碼中寫道 int sum=2+A; 那麼預先處理之後就變成了int sum=2+3;
而定義常量const a=3;則是由編譯器進行處理和分配空間
這裡順便提一下宏定義函數 我們寫個例子
#include <stdio.h>#define SUM( a, b) (a*b)int main(){ int a=5; int b=6; int result=SUM(a+b,b+a);
printf("%d\n",result);}
大膽的猜猜看輸出結果是什嗎?
複製代碼編譯一次,結果是不是與想象中有所不同呢?
如果感到困惑請把它編譯成先行編譯檔案
仔細找找...宏定義函數是不是消失了? 是的 他用代碼塊替換掉了所有調用它的函數..這是宏定義函數比較有趣的一個地方
既然知道了原因,那麼解決方式就一目瞭然了
#define SUM( a, b) ((a)*(b))
這樣編譯輸出的值就是你所期望的了
IOS學習入門準備-C—_3