C++宏替换

例:

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

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月13日 下午4:13
下一篇 2023年2月13日 下午4:14

相关推荐