天天看點

NDK05_C:預處理指令、Define指令一 預處理指令二 常用預處理器三Define指令三 檔案包含四 條件編譯

NDK開發彙總

一 預處理指令

C 語言執行的流程:

  1. 組成程式的每個源檔案通過編譯過程分别轉換成目标代碼(object code)
  2. 各目标檔案由連接配接器 捆綁在一起,形成一個單一而完整的可執行檔案

預處理器不是編譯器,但是它是編譯過程中一個單獨的步驟。

預處理器是一個文本替換工具

所有的預處理器指令都是以井号(#)開頭

而編譯過程又由如下過程組成:

  1. 預處理器處理,在這個階段,預處理器在源代碼上執行一些文本操作。例如:用實際值代替由 #define指令定義的符号以及讀入由#include指令包含的檔案的内容。
  2. 源代碼經過解析,判斷它的語句的意思,這個階段會産生絕大多數錯誤和警告資訊的地方,随後便生成目标代碼。

執行階段:

  1. 程式必須載入到記憶體中。
  2. 程式執行
  3. 程式執行的最後一個階段就是程式終止。

二 常用預處理器

預處理器 說明
#include 導入頭檔案
#if if
#elif else if
#else else
#endif 結束 if
#define 宏定義
#ifdef 如果定義了宏
#ifndef 如果未定義宏
#undef 取消宏定義

三Define指令

1 無參宏定義

#define 辨別符 字元串

定義常量

意義: 就是宏替換的作用,讓 辨別符替換 字元串,這隻是一種簡單的文本替換,預處理程式對它不作任何檢查。如有錯誤,隻能在編譯已被宏展開後的源程式時發現。

反例

#define pint(int*)

pint pa, pb;

本意是定義pa和pb均為int型指針,但實際上變成int* pa,pb;。pa是int型指針,而pb是int型變量。本例中可用typedef來代替define,這樣pa和pb就都是int型指針了。因為宏定義隻是簡單的字元串代換,在預處理階段完成,而typedef是在編譯時處理的,它不是作簡單的代換,而是對類型說明符重新命名,被命名的辨別符具有類型定義說明的功能

無參宏注意事項:

  • 宏名一般用大寫字母表示,以便于與變量差別。
  • 宏定義末尾不必加分号,否則連分号一并替換。
  • 宏定義可以嵌套。
  • 可用#undef指令終止宏定義的作用域。
  • 使用宏可提高程式通用性和易讀性,減少不一緻性,減少輸入錯誤和便于修改。如數組大小常用宏定義。
  • 預處理是在編譯之前的處理,而編譯工作的任務之一就是文法檢查,預處理不做文法檢查。
  • 宏定義寫在函數的花括号外邊,作用域為其後的程式,通常在檔案的最開頭。
  • 字元串" "中永遠不包含宏,否則該宏名當字元串處理。

    宏定義不配置設定記憶體,變量定義配置設定記憶體

2 帶參宏定義

#define宏名(參數) 字元串

例如:

#define INC(x) x+1

y = INC(5);

反例:

#define SQ(r ) rr

Y = SQ(a+b); 結果= a+ba+b;

使用案例:

我們最常用的一種替代方案區最大最小值:

#define MAX(x,y) (((x) > (y)) ? (x): (y))

#define MAX(x, y) ((x) > (y)) ? x: y

#define M

int main() {
    #include "A.txt"

	for (int i = 0; i < 5; i++)
	{
		printf("%d \n", i);
	}

	int max = MAX(3, 5);
	printf("%d \n", max);
#ifdef N
#ifdef M
	printf("%d \n", 110);
#else 
	printf("%d \n", 120);
#endif

#endif

#ifndef X
	printf("%d \n", 130);

#endif
	system("pause");
	return 0;
}
           
  • #define 辨別符 字元串 ,編譯時字元串會替代辨別符
  • #define 的字元串如果後面帶; ,則;會被帶到需要替換辨別符的地方
  • 有ifndef 後面就要跟着 #endif ,可以了解為如果#define 了某個标記,則将執行…

三 檔案包含

檔案包含指令把指定頭檔案插入該指令行位置取代該指令行,進而把指定的檔案和目前的源程式檔案連成一個源檔案。

在程式設計中,檔案包含是很有用的。一個大程式可以分為多個子產品,由多個程式員分别程式設計。有些公用的符号常量或宏定義等可單獨組成一個檔案,在其它檔案的開頭用包含指令包含該檔案即可使用。這樣,可避免在每個檔案開頭都去書寫那些公用量,進而節省時間,并減少出錯。

#include <> 或者 #include “” 差別

< > 和 “ ” 差別在于: 使用《》 表示在包含檔案目錄中去查找 (包含目錄是由使用者在設定環境時設定的include 目錄“解決方案管理器 -> 屬性-> 配置屬性 -> VC++ 目錄”),而不是在目前源檔案目錄去尋找; 使用雙引号就是先從目前源檔案目錄中查找。

四 條件編譯

第一種方式

#ifdef 辨別符 (或者#if defined)
程式段1
#else 
程式段2
#endif
           

或者

#ifdef 辨別符 (或 #if defined 辨別符)
程式段
#endif
           

第二種方式

#ifndef
 #else
#endif
           

第三種方式

#if
#else
#endif
           

在實踐中的作用:

  1. 屏蔽跨平台差異

    在大規模開發過程中,特别是跨平台和系統的軟體裡,可以在編譯時通過條件編譯設定編譯環境。

#ifdef WINDOWS
     #define MYTYPE long
#else
     #define MYTYPE float
#endif
           
  1. 包含程式功能子產品
#ifdef FLV
    Include “fastleavec”
#endif
           

當不許向别的使用者提供該功能,則在編譯之前将首部的FLV 加一下橫線即可

  1. 開關調試資訊
#ifdef DEBUG
     Prinft(“device_open (%d)\n”, file);
#endif
           

這個DEBUG 就是一個開關。可以在整個工程的一個公用的頭檔案中,當我們處于debug 階段的時候就将這個開關打開,當我們程式release 版本裡面的時候就将這個開關關閉。

  1. 避開硬體的限制

    有時一些具體的應用環境的硬體不同,但限于條件本地缺乏這種裝置,可繞過硬體直接寫出預期結果:

#ifndef TEST
   I  =  dial();
#else 
   I = 0;
#endif
           
  1. 防止頭檔案重複包含

    頭檔案可以被頭檔案或者C檔案包含。由于頭檔案包含可以嵌套,C檔案就有可能多次包含同一個檔案; 或者不同的C檔案都包含同一個頭檔案,編譯時就可能出現重複包含的問題。

#ifndef  HEAD_A
#define HEAD_A
     #include <>
#endif
           

繼續閱讀