C語言進階:22、條件編譯使用分析

條件編譯:同一份代碼,產生不同的產品

基本概念:條件編譯的行爲類似於C語言中的if...else...
                條件編譯預編譯指令命令,用於控制是否編譯某段代碼。

#include <stdio.h>

#define C 1

int main()
{
	#if( 1 == C )
	printf("this is first printf...\n");
	#else
	printf("this is second printf...\n");
	#endif
	
	return 0;
}

單步編譯後發現:

int main()
{
 printf("this is first printf...\n");

 return 0;
}

預處理器是對代碼進行調整和文本替換,在這個階段,使用宏定義就能對代碼進行刪除和選擇。

條件編譯只是用來指示預編譯器保留什麼代碼,刪除什麼代碼。
通過宏來實現上述操作。

條件編譯的本質:
        預編譯器根據條件編譯指令有選擇的刪除代碼;
        編譯器不知道代碼分支的存在;
        if...else...語句在運行期進行分支判斷(與條件編譯的本質區別)
        條件編譯指令在預編譯器進行分支判斷;
        可以通過命令行定義宏。

gcc -Dmacro = value file.c
gcc -Dmacro = file.c

對於上面代碼,可是使用命令行進行控制:

~/will$ gcc -DC=1 test.c
~/will$ ./a.out
this is first printf...
~/will$ 

或者這樣使用命令行進行控制:

#include <stdio.h>

int main()
{
	#ifdef C  //更改
	printf("this is first printf...\n");
	#else
	printf("this is second printf...\n");
	#endif
	
	return 0;
}

~/will$ gcc -DC test.c
~/will$ ./a.out
this is first printf...
~/will$ 

單步編譯查看代碼:

delphi@delphi-vm:~/will$ gcc -DC -E test.c -o test.i  //定義C
delphi@delphi-vm:~/will$ 

int main()
{
 printf("this is first printf...\n");  //test.i

 return 0;
}

delphi@delphi-vm:~/will$ gcc -E test.c -o test.i  //不定義C
delphi@delphi-vm:~/will$ 

int main()
{
 printf("this is second printf...\n");

 return 0;
}

#include 的本質      //是和預處理器相關的指令

        #include的本質是將已經存在的文件嵌入到當前文件中

        #include的間接包含同樣會產生嵌入文件內容的操作


問題:間接包含同一個頭文件是否會出現編譯錯誤?

global.h  <-- test.h  <-- test.c -->global.h
會。在預編譯階段將#include包含的文件進行展開,重複包含將會出現重複定義。redefination。

預編譯不會報錯,但是編譯會出現錯誤。重複定義。

如何避免在大的工程中避免這種情況呢?

#ifndef statement  //如果已經定義 則在預處理階段直接刪除接下來的代碼
#define statement

//...//

#endif

條件編譯可以解決頭文件重複包含的編譯錯誤

示例:

#ifndef _HEADER_FILE_H_
#define _HEADER_FILE_H_

//source code

#endif

條件編譯使得我們可以按照不同的條件編譯不同的代碼段,因而可以產生不同的目標代碼。
#if...#else...#endif被預處理器處理,而if...else...語句被編譯器處理。
實際工程中條件編譯主要用於以下兩種情況:
——不同的產品線共用一份代碼
——區分編譯產品的調試版和發佈版

在這裏需要注意的是,與前面通過命令行定義宏的方式不同,此處是直接在外部定義頭文件包含,通過修改頭文件中宏定義來進行條件編譯,如果想通過命令行的方式進行條件編譯,需要先註釋掉頭文件包含。

~/will$ gcc -DDEBUG=1  -DHIGH=1 22-4.c
~/will$ 
~/will$ ./a.out
[22-4.c:23] Enter main() ...
This is the high level product!
1. Query Information.
2. Record Information.
3. Delete Information.
4. High Level Query.
5. Mannul Service.
6. Exit.
[22-4.c:39] Exit main() ...

示例代碼:

#include <stdio.h>
//#include <global.h>

#if DEBUG
	#define LOG(s) printf("[%s:%d] %s", _FILE_, _LINE_, s)
#else
	#define LOG(s) NULL
#endif

#if HIGH
void f()
{
	printf("this is the high level product!\n");
}

#else
void f()
{}
#endif

int main()
{
	LOG("Enter main()...");
	
	f();
	
	printf("1\n");
	printf("2\n");
	printf("3\n");
	
	#if HIGH
	
	printf("4\n");
	printf("5\n");
	printf("6\n");
	
	#else
	printf("4\n");
	#endif
	
	LOG("Exit main()...")
	
	return 0;
}
不同的條件編譯:
~/will$ gcc -DDEBUG=1  -DHIGH=1 22-4.c
~/will$ ./a.out
[22-4.c:23] Enter main()...
this is the high level product!
1
2
3
4
5
6
[22-4.c:41] Exit main()...

delphi@delphi-vm:~/will$ gcc 22-4.c
delphi@delphi-vm:~/will$ ./a.out
1
2
3
4
小結:
            通過編譯器命令行能夠定於預處理器使用的宏
            條件編譯可以避免重複包含同一個頭文件
            條件編譯在工程開發中可以定義不同產品線的代碼
            條件編譯可以定義不同產品的發佈版和調試版

    

發佈了83 篇原創文章 · 獲贊 12 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章