例:
define TEST_VAL 100
现在要将TEST_VAL转换成字符串使用:
define TO_STR(x) #x
define STR(x) TO_STR(x)
定义了上述两个宏之后在代码中这样使用
STR(TEST_VAL) 返回的便是字符串 “100”
为什么中间必须有一个过渡的宏TO_STR呢?宏被作为参数传入另一个宏时,预处理器会尝试将所有的宏替换成已经定义的字符串,但是如果宏的定义中带有 ## #这样的连接符,则参数宏不会被替换。
于是 STR(TEST_VAL) => TO_STR(100) => #100 => "100" 这个是因为STR的定义中不含有# ## ,而TEST_VAL在第一次替换时,便替换为了100
如果做一下定义:
define STR2(x) #x
则 STR2(TEST_VAL) => #TEST_VAL => "TEST_VAL"
注:预处理器只会对宏进行简单的字符串替换。因此:
define DBL(x) (x + x) , 该定义必须加上括号.
注:对于多行的宏建议使用do{}while(0) 的形式定义,比如
#define CALC(x) \
do { \
if (x > 0) \
cout << "x > 0"; \
else \
cout << "x < 0"; \
}while(0)
这样在使用宏的使用可以在尾部添加上分号,同时保证了宏定义的代码不会被外部干扰,也不会干扰外部。
使用do{}while(0)的目的就是为了添加上分号,而且很多编译器会能够将这种循环优化掉。
单单的使用{}则不能够在尾部添加分号。因为分号是多余的。
补充一个例子
#include <iostream>
#include <cmath>
#define CALC_O(x , y) \
do {\
int sum = (x) + (y); \
std::cout << "sum = " << sum << std::endl; \
} while(0)
int main(int argc , char** argv)
{
if (int x = 3)
CALC_O(x , 5);
else
CALC_O(6 , 7);
return 0;
}
在上述例子中,如果不使用do--while封装,别的方案都容易出问题。
VC编译器和g++编译器在对##的处理是有有所区别的。举个例子
//! 这里使用Qt中的标识编译环境的宏
#ifdef Q_OS_MAC
# define PLATFORM mac
#elif defined(Q_OS_WIN)
# ifdef Q_OS_WIN64
# define PLATFORM winx64
# else
# define PLATFORM winx86
# endif
#else
#error "The platform is not supported!"
#endif
#ifdef __PROEDUCT_A__
# define PRODUCT a
#else
# define PRODUCT b
#endif
#define WEB_URL
#define TO_STR(x) #x
#define CONNECT_STR TO_STR(PLATFORM ## PRODUCT)
#define PRODUCT_VERSION CONNECT_STR(PLATFORM , PRODUCT)
原文链接: https://www.cnblogs.com/linannk/p/5549263.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/234345
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!