C語言的#define用法
1. 簡單的宏定義
#define MAXSIZE 1000
// 有點像簡單的文本替換
2. define的函數定義
// 同樣類似簡單文本替換
#define Add(a,b) a+b
// 要注意可能會出現運算優先級的問題,比如
c*Add(a,b)*d;
// 本意是c*(a+b)*d,但是計算機可能理解為:c*a+b*d
3. 宏的單行定義和多行定義
宏定義中允許包含兩行以上命令的情形,此時必須在最右邊加上\
且該行\
后不能再有任何字符,連注釋部分都不能有,下面的每行最后的一定要是\
,\
后面加一個空格都會報錯,更不能跟注釋。
#define max(a,b) \
(((a)>(b))?(a):(b))\
4. 條件編譯
在大規模的開發過程中,特別是跨平台和系統的軟件里,define最重要的功能是條件編譯。
#ifdef WINDOWS
...
#endif
#ifdef LINUX
...
#endif
5. 取消定義宏
//定義宏
#define [MacroName] [MacroValue]
//取消定義
#undef [MacroName]
6. 重復包含(定義)
由於頭文件包含可以嵌套,那么C文件就有可能包含多次同一個頭文件,就可能出現重復定義的問題的。通過條件編譯開關來避免重復包含(重復定義)
#ifndef __headerfileXXX__
#define __headerfileXXX__
//頭文件內容
#endif
7. 重新定義類型
重新定義一些類型,防止由於各種平台和編譯器的不同,而產生的類型字節數差異,方便移植。
補充:關於unsiged char和char
首先在內存中,char與unsigned char沒有什么不同,都是一個字節,唯一的區別是,char的最高位為符號位,因此char能表示-128~127,unsigned char沒有符號位,因此能表示0~255,這個好理解,8個bit,最多256種情況,因此無論如何都能表示256個數字。
在實際使用過程種有什么區別呢?主要是符號位,但是在普通的賦值,讀寫文件和網絡字節流都沒什么區別,反正就是一個字節,不管最高位是什么,最終的讀取結果都一樣,只是你怎么理解最高位而已,在屏幕上面的顯示可能不一樣。
二者的最大區別是:但是我們卻發現在表示byte時,都用unsigned char,這是為什么呢?首先我們通常意義上理解,byte沒有什么符號位之說,更重要的是如果將byte的值賦給int,long等數據類型時,系統會做一些額外的工作。如果是char,那么系統認為最高位是符號位,而int可能是16或者32位,那么會對最高位進行擴展(注意,賦給unsigned int也會擴展)而如果是unsigned char,那么不會擴展。最高位若為0時,二者沒有區別,若為1時,則有區別了。同理可以推導到其它的類型,比如short, unsigned short,等等。
typedef unsigned char boolean; /* Boolean value type. */
8. 一些常用用法
1. 得到一個field在結構體中的偏移量
#define OFFSETOF(type, field) ((size_t)&(((type *)0)->field))
(type*)0
表示把0地址當成type類型的指針 ((type *)0)->field
表示對於
域的變量。前面加上&表示取得地址(也就是相對於0的偏移量),然后將該偏移量轉換為size_t類型的數據
2. 得到一個結構體中field所占用的字節數
#define FPOS( type, field ) ( (dword) &(( type *) 0)-> field )
3. 按照LSB格式把兩個字節轉化為一個Word
#define FLIPW( ray ) ( (((word) (ray)[0]) * 256) + (ray)[1] )
4. 得到一個變量的地址(word寬度)
#define B_PTR(var) ((byte*)(void *) &(var))
#define W_PTR( var ) ((word *)(void *) &(var))
5. 得到一個字的高位和低位字節
#define WORD_LO(xxx) ((byte) ((word)(xxx) & 255))
#define WORD_HI(xxx) ((byte) ((word)(xxx) >> 8))
9. 使用一些宏跟蹤調試
五個預定義的宏名:
__LINE__ 及 __FILE__ //宏指示,#line指令可以改變它的值,簡單的講,編譯時,它們包含程序的當前行數和文件名。
__DATE__ 宏指令含有形式為月/日/年的串,表示源文件被翻譯到代碼時的日期。
__TIME__ 宏指令包含程序編譯的時間。時間用字符串表示,其形式為:分:秒
__STDC__ 宏指令的意義是編譯時定義的。一般來講,如果__STDC__已經定義,編譯器將僅接受不包含任何非標准擴展的標准C/C++代碼。如果實現是標准的,則宏__STDC__含有十進制常量1。如果它含有任何其它數,則實現是非標准的。;
// 定義_DEBUG
#ifdef _DEBUG
#define DEBUGMSG(msg,date) printf(msg);printf(“%d%d%d”,date,_LINE_,_FILE_)
#else
#define DEBUGMSG(msg,date)
#endif
10. 一些特殊的標識符
## 是簡單的連接符,#@用來給參數加單引號,#用來給參數加雙引號即轉成字符串。