提到預處理,不由想起來一個經典問題。
C語言簡單嗎? 簡單,C語言沒多少語法,很快就學會。
的確,C語言如果沒有預處理,的確會簡單很多。但一旦有了,就復雜度上升了好幾個等級。
C語言支持面向對象嗎? 可以,預處理能幫你實現。
C語言有異常處理嗎?可以,預處理能幫你實現。
預處理就是一個潘多拉盒子,可以讓你上天堂,也可以讓你下地獄。(笑話)
在認真學習C語言時,建議下載C語言規范:
C89 嵌入式領域使用得多,芯片公司提供的工具很多還不支持C99
C99
規范不是用來看的,是用來查的。(笑話)
關於C語言編譯器代碼,可以參考下面2個:
TinyCC (http://bellard.org/tcc/)
gcc (http://mirror.bjtu.edu.cn/gnu/gcc/)
實際項目中用得最多的就是下面幾個:
#include 文件
注意:不要受C語言教材的影響,以為只可以加載.h文件。這是一個最大的思維定式。
可以加載任何文本文件。
比如 test.test 內容如下:
int myTestAry[] = { 0, 1, 2,3 ,4, 5};
#include "test.test"
這樣,有什麼好處呢?
最大的好處是可以和其他語言結合。
比如,我們可以用Python生成符合C語言語法的文本,比如,字體數據,圖片數據等。
#define
#ifdef
#undef
#if
#endif
5個指令一起配合,能對源代碼進行版本控制。
比如最常見的
#ifdef WIN32 /* 如果當前系統是WIN32平台 */
#endif
當然,#define定義的控制變量,也可以在編譯腳本中用 -D變量名=變量值 替換。
#define 還有一個常見的作用是定義常量。
#define PI 3.1415926
不過,這些都是小用途。
真正強大的是用#define構建復雜機制。可惜,實際項目中為了可讀性,基本被禁止。
有興趣的可以搜,C語言與面向對象 C語言與異常處理 C語言與模板 或者看MFC中的宏。
這是一個讓人痛苦並快樂的功能。
實際項目中用得最多的是打印Log語句。
比如跟蹤函數執行:
#define FUNC_BEGIN() do { printf("Enter %s %d \n", __FUNCTION__, __LINE__); } while(0)
#define FUNC_END() do { printf("Leave %s %d \n", __FUNCTION__, __LINE__); } while(0)
在函數進入的地方,加
FUNC_BEGIN();
函數返回的地方加:
FUNC_END();
更復雜的打印語句:
#define MYPRINT(...) do { printf(__VA_ARGS__); } while(0)
__FUNCTION__: 當前函數名,由編譯器決定
__LINE__: 當前代碼行號
__VA_ARGS__: 可變參數
#error
編譯報錯。可以在代碼中加下面語句進行測試下。()
#error "不支持"
#pragma
控制編譯器,與編譯器實現有關。
實際項目中為了可移植性用得不多。
對於特定項目,建議使用前需要參考編譯器說明,並在項目風險管理中加以說明。(這一點很重要,對項目跨平台移植很有意義)
總而言之,預處理是一個編譯器展示自我的地方,也是一個讓大家瘋狂,讓大家迷失的地方。
對於開發者來說,這就是天堂,對項目經理來說,這就是地獄。()