define普通用法
1.1 定义常量
1.2 定义简单函数
1
| #define MAX(a,b) (a>b ? a : b)
|
1.3 避免重复定义
1 2 3 4
| #ifndef VEHICLE_H #define VEHICLE_H
#endif
|
define高级用法
2.1 define中的三个特殊符号:#,##,#@
字符串化(stringizing) [#]
将传入的参数名转换为用一对双引号引用的字符串。
1 2 3 4
| #define StrFormat(x) #x
|
- 传入参数前面和后面的空格会被忽略。
- 传入参数中间存在空格,编译器将各个子字符串之间用一个空格连接。
符号连接(token-pasting)[##]
将宏定义中的多个参数连接形成一个参数。
1 2 3 4 5
| #define Cat(x,y) x##y
|
字符化(charizing)[#@]
将传入的单字符参数名转换为字符。
多行定义[\]
当定义的宏不能用一行表达完整时,可以用 \ 表示下一行继续此宏的定义。
1 2 3 4 5 6
| #define switch(a,b) do { \ int t = 0; \ t = a; \ a = b; \ b = t; \ } while(0)
|
do{}while(0)
将宏用 do{}while(0) 将宏包裹起来使其成为一个独立的语法单元,从而不会与上下文发生混淆,同时大部分编译器能够识别 do{}while(0) 这种无用的循环,并对其进行优化,所以使用这种方法不会导致性能的降低。
主要应用于下面三种情况:
- 空的宏定义,避免Warning。
- 复杂逻辑,需要一个独立的block。
- 宏用在判断语句之后。
为什么不用{}?
1 2 3 4 5 6
| #define switch(a,b) {int t = 0; t = a; a = b; b = t;}
if (x > y) switch(x,y); else
|
2.2 标准预定义宏
- __LINE__:在源代码中插入当前源代码行号;
- __FILE__:在源文件中插入当前源文件名;
- __DATE__:在源文件中插入当前的编译日期
- __TIME__:在源文件中插入当前编译时间;
- __STDC__:当要求程序严格遵循ANSI C标准时该标识被赋值为1;
- __cplusplus:当编写C++程序时该标识符被定义。
2.3 可变参数宏
1
| #define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
|
如果可变参数被忽略或为空,’##’操作将使预处理器(preprocessor)去除掉它前面的那个逗号。
TDM 项目中用到的宏
3.1 平台宏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
#if defined(_WIN32) || defined(_WIN64) #define __WINDOWS__ #elif defined(__APPLE__) #include "TargetConditionals.h" #if TARGET_OS_IOS || TARGET_OS_IPHONE #define _IOS #else #define _MAC #endif #elif defined(__ANDROID__) #define _AOS #endif
|
3.2 字节序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
| #if defined(_WIN32) || defined(_WIN64) #if defined (LITTLEENDIAN) && (LITTLEENDIAN > 0) #define A_OS_LITTLEENDIAN #else #define A_OS_BIGENDIAN #endif #else #if __BYTE_ORDER == __LITTLE_ENDIAN #define A_OS_LITTLEENDIAN #else #define A_OS_BIGENDIAN #endif #endif
#if (defined(_WIN32) || defined(_WIN64)) #define A_OS_SWAP64(x) \ ( (((x) & (uint64_t)0xff00000000000000) >> 56) \ | (((x) & (uint64_t)0x00ff000000000000) >> 40) \ | (((x) & (uint64_t)0x0000ff0000000000) >> 24) \ | (((x) & (uint64_t)0x000000ff00000000) >> 8) \ | (((x) & (uint64_t)0x00000000ff000000) << 8) \ | (((x) & (uint64_t)0x0000000000ff0000) << 24) \ | (((x) & (uint64_t)0x000000000000ff00) << 40) \ | (((x) & (uint64_t)0x00000000000000ff) << 56)) #else #define A_OS_SWAP64(x) \ ( (((x) & (uint64_t)0xff00000000000000LL) >> 56) \ | (((x) & (uint64_t)0x00ff000000000000LL) >> 40) \ | (((x) & (uint64_t)0x0000ff0000000000LL) >> 24) \ | (((x) & (uint64_t)0x000000ff00000000LL) >> 8) \ | (((x) & (uint64_t)0x00000000ff000000LL) << 8) \ | (((x) & (uint64_t)0x0000000000ff0000LL) << 24) \ | (((x) & (uint64_t)0x000000000000ff00LL) << 40) \ | (((x) & (uint64_t)0x00000000000000ffLL) << 56)) #endif
#define A_OS_SWAP32(x) \ ( (((x) & 0xff000000) >> 24) \ | (((x) & 0x00ff0000) >> 8) \ | (((x) & 0x0000ff00) << 8) \ | (((x) & 0x000000ff) << 24))
#define A_OS_SWAP16(x) \ ( (((x) & 0xff00) >> 8) \ | (((x) & 0x00ff) << 8))
#ifdef A_OS_LITTLEENDIAN #define a_ntoh64(x) A_OS_SWAP64(x) #define a_hton64(x) A_OS_SWAP64(x) #define a_ntoh32(x) A_OS_SWAP32(x) #define a_hton32(x) A_OS_SWAP32(x) #define a_ntoh16(x) A_OS_SWAP16(x) #define a_hton16(x) A_OS_SWAP16(x) #else #define a_ntoh64(x) (x) #define a_hton64(x) (x) #define a_ntoh32(x) (x) #define a_hton32(x) (x) #define a_ntoh16(x) (x) #define a_hton16(x) (x) #endif
|
3.3 符号导出
1 2 3 4 5 6 7 8 9 10 11 12 13
| #if defined(_WIN32) || defined(_WIN64) #ifdef TDM_BUILD #define TDM_EXPORT __declspec(dllexport) #else #define TDM_EXPORT __declspec(dllimport) #endif #else #if __GNUC__ >= 4 #define TDM_EXPORT __attribute__ ((visibility ("default"))) #else #define TDM_EXPORT #endif #endif
|
查看编译器预定义的宏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| # C编译(方法1) gcc -dM -E - < /dev/null gcc -dM -E -include sys/socket.h - < /dev/null
# C编译(方法2) echo | gcc -dM -E - echo "#include <sys/socket.h>" | gcc -E -dM -
# C++编译(方法1) g++ -dM -E -x c++ -std=c++11 < /dev/null g++ -dM -E -x c++ -std=c++11 -include sys/socket.h - < /dev/null
# C++编译(方法2) echo | gcc -x c++ -std=c++11 -dM -E - echo "#include <stdlib.h>" | gcc -x c++ -std=c++11 -dD -E -
|
参考文档:
http://huqunxing.site/2016/11/14/C++%20define%20%E4%B8%AD%E7%9A%84%E7%89%B9%E6%AE%8A%E7%AC%A6%E5%8F%B7/