设为首页 加入收藏

TOP

C++预处理详解(五)
2014-03-10 12:54:13 来源: 作者: 【 】 浏览:351
Tags:处理 详解

 

  宏替换

  #define 定义宏替换,#define 之后的宏都将被替换为宏的定义,直到用 #undef 解除该宏的定义。宏定义分为不带参数的常量宏(Object-like macros)和带参数的函数宏(Function-like macros)。其格式如下:

  #define identifier replacement-list                             (1)

  #define identifier( parameters ) replacement-list         (2)

  #define identifier( parameters, … ) replacement-list    (3) (since C++11)

  #define identifier( … ) replacement-list                      (4) (since C++11)

  #undef identifier                                                     (5)

  对于有参数的函数宏,在replacement-list中,"#"置于identifier面前表示将identifier变成字符串字面值,"##"连接,下面的例子来自cppreference.com:

  #include <iostream>

  //make function factory and use it

  #define FUNCTION(name, a) int fun_##name() { return a;}

  FUNCTION(abcd, 12);

  FUNCTION(fff, 2);

  FUNCTION(kkk, 23);

  #undef FUNCTION

  #define FUNCTION 34

  #define OUTPUT(a) std::cout 《 #a 《 '\n'

  int main()

  {

  std::cout 《 "abcd: " 《 fun_abcd() 《 '\n';

  std::cout 《 "fff: " 《 fun_fff() 《 '\n';

  std::cout 《 "kkk: " 《 fun_kkk() 《 '\n';

  std::cout 《 FUNCTION 《 '\n';

  OUTPUT(million);               //note the lack of quotes

  std::cin.get();

  return 0;

  }

  可变参数宏是C++11新增部分(来自C99),使用时用__VA_ARGS__指代参数"…",一个摘自C++标准2011的例子如下(标准举的例子就是不一样啊):

  #define debug(…) fprintf(stderr, __VA_ARGS__)

  #define showlist(…) puts(#__VA_ARGS__)

  #define report(test, …) ((test) puts(#test) : printf(__VA_ARGS__))

  debug("Flag");

  debug("X = %d\n", x);

  showlist(The first, second, and third items.);

  report(x>y, "x is %d but y is %d", x, y);

  这段代码在预处理后产生如下代码:

  fprintf(stderr, "Flag");

  fprintf(stderr, "X = %d\n", x);

  puts("The first, second, and third items.");

  ((x>y) puts("x>y") : printf("x is %d but y is %d", x, y));

  在上面条件编译就讲到,有时用 #ifdef macro_NAME 来识别一些信息,C++标准指定了一些预定义宏,列在下表中(C++11新增宏已标出):

  Predefined macros

  Meaning

  Remark

  __cplusplus

  在C++98中定义为199711L,C++11中定义为201103L

  __LINE__

  指示所在的源代码行数(从1开始),十进制常数

  __FILE__

  指示源文件名,字符串字面值

  __DATE__

  处理时的日期,字符串字面值,格式"Mmm dd yyyy"

  __TIME__

  处理时的时刻,字符串字面值,格式"hh:mm:ss"

  __STDC__

  指示是否符合Standard C,可能不被定义

  wikipedia条目

  __STDC_HOSTED__

  若是Hosted Implementation,定义为1,否则为0

  C++11

  __STDC_MB_MIGHT_NEQ_WC__

  见ISO/IEC 14882:2011

  C++11

  __STDC_VERSION__

  见ISO/IEC 14882:2011

  C++11

  __STDC_ISO_10646__

  见ISO/IEC 14882:2011

  C++11

  __STDCPP_STRICT_POINTER_SAFETY__

  见ISO/IEC 14882:2011

  C++11

  __STDCPP_THREADS__

  见ISO/IEC 14882:2011

  C++11

  其中上面5个宏一定会被定义,下面从__STDC__开始的宏不一定被定义,这些预定义宏不能被 #undef.使用这些宏的一个例子如下(连续字符串字面值会被自动相连,"ab""cde" 等价于 "abcde"):

  1 #include <iostream>

  2 int main()

  3 {

  4 #define PRINT(arg) std::cout 《 #arg": " 《 arg 《 '\n'

  5     PRINT(__cplusplus);

  6     PRINT(__LINE__);

  7     PRINT(__FILE__);

  8     PRINT(__DATE__);

  9     PRINT(__TIME__);

  10 #ifdef __STDC__

  11     PRINT(__STDC__);

  12 #endif

  13     std::cin.get();

  14     return 0;

  15 }

  这些宏经常用于输出调试信息。预定义宏一般以"__"作为前缀,所以用户自定义宏应该避开"__"开头。

  应当指出的是,现代的C++程序设计原则不推荐适用宏定义常量或函数宏,应该尽量少的使用 #define ,如果可能,用 const 变量或 inline 函数代替。

  重定义行号和文件名

  从 #line number ["filename"] 的下一行源代码开始, __LINE__ 被重定义为从 number 开始,__FILE__ 被重定义"filename"(可选),一个例子如下:

  1 #include <iostream>

  2 int main()

  3 {

  4 #define PRINT(arg) std::cout 《 #arg": " 《 arg 《 '\n'

  5 #line 999 "WO"

  6

  7     PRINT(__LINE__);

  8     PRINT(__FILE__);

  9     std::cin.get();

  10     return 0;

  11 }

        

首页 上一页 2 3 4 5 下一页 尾页 5/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C++对象占用内存大小的思考 下一篇C++ 类模板

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·HTTPS 详解一:附带 (2025-12-26 02:20:37)
·TCP/IP协议到底在讲 (2025-12-26 02:20:34)
·TCP和UDP在socket编 (2025-12-26 02:20:32)
·有没有适合新手练习 (2025-12-26 01:48:47)
·用清华镜像网怎么下 (2025-12-26 01:48:44)