天天看點

C/C++宏定義 摘抄

 #define是C語言中提供的宏定義指令:

用來将一個辨別符定義為一個字元串,該辨別符被稱為宏名,被定義的字元串稱為替換文本。

#define<宏名>  <字元串>

#define<宏名> (<參數表>)<宏體>

宏展開是在預處理階段完成的,這個階段把替換文本隻是看作一個字元串,并不會有任何的計算發生

#define中的三個特殊符号:#,##,#@

  1. #define Cat(x,y) x##y                //token-pasting 符号連接配接操作符
  2. #define ToChar(x)#@x                // charizing 字元化操作符
  3. #define ToString(x)#x                  // stringizing 字元串化操作符

ANSI标準說明了五個預定義的宏名。它們是: 

  1. _LINE_ 
  2. _FILE_ 
  3. _DATE_ 
  4. _TIME_ 

用#pragma導出DLL函數

__declspec(dllexport)  //導出函數

__declspec(dllimport)  //申明導入函數

重命名導出函數 #pragma comment(linker,"/EXPORT:[email protected]")

/EXPORT:entryname[,@ordinal[,NONAME]][,DATA]

   @ordinal 指定順序;NONAME 指定隻将函數導出為序号;DATA 關鍵字指定導出項為資料項。

指定連結庫 #pragma comment(lib, "WSock32.lib")

#pragma warning( disable : 4507 34; once : 4385; error : 164 ) //編譯器忽略4507 和34, 僅報告1次4385  把164警告作為錯誤。

#pragma message(“消息文本”)    //當編譯器遇到這條指令時就在編譯輸出視窗中将消息文本列印出來。

另一個使用得比較多的pragma參數是code_seg。格式如:

#pragma code_seg( ["section-name"[,"section-class"] ] )

它能夠設定程式中函數代碼存放的代碼段,當我們開發驅動程式的時候就會使用到它。

#pragma once (比較常用)

#pragma hdrstop表示預編譯頭檔案到此為止,後面的頭檔案不進行預編譯。

#pragma resource "*.dfm"表示把*.dfm檔案中的資源加入工程。

常用的一些宏定義

1 防止一個頭檔案被重複包含 

  1. #ifndef BODYDEF_H
  2. #define BODYDEF_H
  3.  //頭檔案内容 
  4. #endif

  2 得到指定位址上的一個位元組或字

  1. #define MEM_B( x) ( *( (byte*) (x) )) 
  2. #define MEM_W( x) ( *( (word*) (x) ))

例子:

  1. int main()
  2. {
  3.     int bTest = 0x123456;
  4.     byte m = MEM_B((&bTest));
  5.     int n = MEM_W((&bTest));
  6.     return 0;
  7. }

3 得到一個field在結構體(struct)中的偏移量  

  1. #defineOFFSETOF( type, field) ( (size_t) &(( type*) 0)-> field)

得到一個field在結構體(struct type)中的偏移量

  1. #define OFFSETOF(type, field) ((size_t)&(((type *)0)->field))
  2. (type *)0:把0位址當成type類型的指針。
  3. ((type *)0)->field:對應域的變量。
  4. &((type *)0)->field:取該變量的位址,其實就等于該域相對于0位址的偏移量。
  5. (size_t)&(((type *)0)->field):将該位址(偏移量)轉化為size_t型資料。

ANSI C标準允許任何值為0的常量被強制轉換成任何一種類型的指針,并且轉換結果是一個NULL指針,是以((s*)0)的結果就是一個類型為s*的NULL指針。如果利用這個NULL指針來通路s的成員當然是非法的,但&(((s*)0)->m)的意圖并非想存取s字段内容,而僅僅是計算當結構體執行個體的首址為((s*)0)時m字段的位址。聰明的編譯器根本就不生成通路m的代碼,而僅僅是根據s的記憶體布局和結構體執行個體首址在編譯期計算這個(常量)位址,這樣就完全避免了通過NULL指針通路記憶體的問題。

注:

1. 有人這樣表達:

  1. #define OFFSETOF(type, field) ((size_t) \
  2.     ((char *)&((type *)0)->field - (char *)(type *)0))

4 得到一個結構體中field所占用的位元組數 

  1. #define FSIZ( type, field) sizeof(((type *) 0)->field)

5 得到一個變量的位址(word寬度) 

  1. #define B_PTR( var) ( (byte *)(void *) &(var)) 
  2. #define W_PTR( var) ( (word *)(void *) &(var))

6 将一個字母轉換為大寫

  1. #define UPCASE( c) ( ((c)>= ''a'' &&(c) <= ''z'')? ((c)- 0x20) : (c))

7 判斷字元是不是10進值的數字

  1. #define DECCHK( c) ((c)>= ''0'' &&(c) <= ''9'')

8 判斷字元是不是16進值的數字 

  1. #define HEXCHK( c) ( ((c)>= ''0'' &&(c) <= ''9'')||((c)>= ''A'' &&(c) <= ''F'')||((c)>= ''a'' &&(c) <= ''f''))

9 防止溢出的一個方法

  1. #define INC_SAT( val) (val = ((val)+1> (val))? (val)+1: (val))

10 傳回數組元素的個數 

  1. #define ARR_SIZE( a) ( sizeof( (a)) / sizeof( (a[0])) )

多層替換 #define DECVAL_1 0

#define DECVAL_2 1

#define DECVAL_3 2

#define DECVAL_4 3

#define DECVAL_5 4

#define DECVAL_6 5

#define DECVAL_7 6

#define DECVAL_8 7

#define DECVAL_9 8

#define DECVAL( n ) DECVAL_##n

參考: http://blog.csdn.net/witch_soya/article/details/7645493 http://blog.chinaunix.net/uid-21372424-id-120086.html