Summary
1)條件編譯的行為類似於
C語言中的if else
;條件編譯是預編譯指示命令
,用於控制是否編譯某段程式碼
;
2)預編譯器
根據條件編譯指令有選擇的刪除程式碼
,所以編譯器不知道
程式碼分支的存在
3)if else在執行期
進行分支判斷,一定會被編進目的碼
;條件編譯指令
在預編譯期
進行分支判斷,可能產生不同的程式碼段,因此編進目的碼的程式碼段不確定
4)可以通過命令列定義巨集
:gcc -Dmacro=val file.c
或gcc -Dmacro file.c
5)#include
本質
是將已經存在的檔案內容插入
到當前檔案中;#include
的間接包含同樣會產生嵌入檔案內容操作。條件編譯指令#ifndef _FILE_H_ #define _FILE_H #endif
可以解決這種標頭檔案重複包含
的錯誤。
6)條件編譯指令只是可以在同一個.c檔案中,防止重複包含
;如果標頭檔案中有了符號的定義
,但是在一個工程的不同c檔案裡都進行了include
,這時候編譯這兩個檔案也會有重複定義
的錯誤(因為兩份include在各自的c檔案裡都定義了一個global,在同一個全域性作用域裡定義了同名的symbol)。所以,標頭檔案中只宣告、不定義
!
7)工程中的條件編譯主要用於:不同的產品線共用一份程式碼
;區分編譯產品的除錯版和釋出版
條件編譯分析
條件編譯的行為類似
於C語言中的if...else...
;
條件編譯是預編譯指示命令
,用於控制是否編譯
某段程式碼;
1、條件編譯於if...else的區別
預編譯器
根據條件編譯指令有選擇的刪除程式碼
,所以編譯器不知道
程式碼分支的存在if...else
語句在執行期
進行分支判斷;條件編譯指令
在預編譯期
進行分支判斷- 可以通過
命令列定義巨集
:gcc -Dmacro=val file.c
或者gcc -Dmacro file.c
#define C1
int main()
{
#if (C==1)
printf("if true\n");
#else
printf("if false\n");
#endif
return 0;
}
gcc -E test.c -o test.i
// 單步編譯後得到的中間檔案
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.c"
int main()
{
printf("if true\n");
return 0;
}
分析:
- 經過預編譯期的處理後,得到的中間檔案中#if #else #endif都被刪掉了,這也說明了上面的
預編譯器根據條件編譯指令有選擇的刪除程式碼
,所以編譯器在拿到中間.i檔案後,根本就不知道這些程式碼分支的存在。 - 也說明,
#if #else #endif是在預編譯期進行判斷
的,而if else是在執行期才會判斷
// 上述程式碼中去掉#define C 1 // 使用命令來定義巨集 gcc -DC=1 test.c 編譯後的執行結果為:if true gcc -DC test.c gcc -DC test.c 編譯後的執行結果為:if true
使用#ifdef #else #endif
進行預編譯分支判斷:
#ifdef C printf("yes, defined"); #else printf("no, undefined"); #endif 以上程式碼進行編譯: gcc -DC test.c 輸出:yes, defined gcc test.c 輸出:no, undefined
2、條件編譯解決標頭檔案重複包含的編譯錯誤
#include
本質
是將已經存在的檔案內容插入
到當前檔案中#include
的間接包含同樣會產生嵌入檔案內容操作。
對以上程式碼進行單步編譯
gcc -E test.c -o test.i
gcc -S test.i -o test.s
分析:單步編譯後,在中間.i檔案中,global的定義出現了2次,後續的編譯過程自然會出現重定義的錯誤。
重複包含的解決方式:在標頭檔案test.h和global.h中加上條件編譯指令
。
#ifndef _HEADER_FILE_H_
#define _HEADER_FILE_H_
// SRC
#endif
注意:條件編譯指令只是可以在同一個.c檔案中,防止重複包含
;如果標頭檔案中有了符號的定義
,但是在一個工程的不同c檔案裡都進行了include
,這時候編譯這兩個檔案也會有重複定義
的錯誤(因為兩份include在各自的c檔案裡都定義了一個global,在同一個全域性作用域裡定義了同名的symbol)。所以,標頭檔案中只宣告、不定義
!
示例程式碼:
依舊是上面的test.c test.h global.h,再加一個test2.c檔案,其中#include "test.h"
執行:gcc test.c test2.c
輸出:multiple definition of 'global'
3、條件編譯工程中的應用
if else
被編譯器
處理,必然被編譯進目的碼
;#if #else #endif
被預編譯器
處理,可以按不同的條件編譯不同的程式碼段,因而會產生不同的目的碼
- 工程中的條件編譯主要用於:
不同的產品線共用一份程式碼
;區分編譯產品的除錯版和釋出版
本文總結自“狄泰軟體學院”唐佐林老師《C語言進階課程》。
如有錯漏之處,懇請指正。