宏定义后注意细节

宏定义的优点不说了,比如:#defineCC_DISCRETE_BOOST   "DAB" 则以下你用CC_DISCRETE_BOOST就可以代表 “DAB”,但是会出现下面的问题:

如程序需要输入参数,我的输入参数为: -bt  CC_DISCRETE_BOOST

部分关键代码如下:

if( !prmName.compare("-bt" ) )
    {
        boost_type = !val.compare(CC_DISCRETE_BOOST ) ? CvBoost::DISCRETE :
                     !val.compare( CC_REAL_BOOST) ? CvBoost::REAL :
                     !val.compare(CC_LOGIT_BOOST ) ? CvBoost::LOGIT :
                     !val.compare(CC_GENTLE_BOOST ) ? CvBoost::GENTLE : -1;
        if (boost_type == -1)
            res = false;
    }


(部分代码省略)

String boostTypeStr =boost_type == CvBoost::DISCRETE ? CC_DISCRETE_BOOST :
                          boost_type ==CvBoost::REAL ? CC_REAL_BOOST :
                          boost_type ==CvBoost::LOGIT  ? CC_LOGIT_BOOST :
                          boost_type == CvBoost::GENTLE ?CC_GENTLE_BOOST : String();
CV_Assert(!boostTypeStr.empty() );   //CV_Assert()若括号中的表达式值为false,则返回一个错误信息

但是编译错误如下图:


意思就是boostType是空的。。想了半天怀疑是选择运算符结合问题我理解错了,,,后来发现不是。。又过了一阵才反应过来,我输入参数的问题,虽然程序中定义了

#defineCC_DISCRETE_BOOST   "DAB",但是我输入的东西应该是变量实际的值即“DAB”,而不是CC_DISCRETE_BOOST  ,修改后输入参数为-bt DAB,编译成功。



<think>嗯,用户问的是关于C/C++宏定义嵌套的使用方法和注意事项。首先,我需要回忆一下宏嵌套的基本概念。根据引用[2],宏定义可以嵌套,已定义的宏可以用来定义新的宏。比如先定义一个宏A,再用A来定义宏B。这应该是最基础的用法。 接下来,用户可能想知道具体的例子。比如,如何正确嵌套,或者可能遇到的常见问题。比如,展开顺序的问题。根据引用[2],宏替换在预处理器中是递归展开的,但遇到被替换的宏名时会停止展开。这时候需要用中间层或者延迟展开的技术,比如使用间接宏或者辅助宏。 然后,注意事项部分。用户可能需要了解宏展开的规则,比如参数替换的时机、宏的作用域。比如,嵌套宏如果涉及到参数,需要确保参数在展开时正确传递。另外,宏的作用域是从定义处到文件结束,或者被#undef取消,所以嵌套时要注意定义的顺序和位置。 还有,用户的问题可能涉及到更复杂的嵌套情况,比如多层嵌套或者可变参数宏。引用[3]提到了可变参数宏使用__VA_ARGS__,这可能和嵌套结合使用时需要注意参数的传递。例如,在嵌套宏中使用可变参数,需要正确处理省略号的情况。 另外,引用[1]提到不同编译器对宏的支持可能不同,比如嵌套展开的细节可能依赖于编译器实现。这时候需要提醒用户注意编译器的差异,尤其是在跨平台开发时。 可能还需要考虑宏展开后的副作用,比如多次求值的问题。例如,如果宏参数中有副作用表达式,嵌套展开可能导致多次执行,影响程序行为。这时候应该建议使用内联函数或者避免在宏参数中使用有副作用的表达式。 总结一下,回答的结构应该包括基本用法、展开规则、常见技巧、注意事项,以及可能的编译器差异。同时,结合引用中的内容,给出具体的例子,比如延迟展开的例子、可变参数宏的嵌套使用,以及作用域和重复定义的问题。</think>### C/C++宏定义嵌套的用法及注意事项 #### 一、嵌套宏定义的基础用法 嵌套宏定义允许通过已定义的宏构建新的宏。例如: ```c #define PI 3.1415926 #define CIRCLE_AREA(r) (PI * (r) * (r)) // 嵌套使用PI ``` 此处`CIRCLE_AREA`通过已定义的`PI`实现面积计算[^2]。 #### 二、宏展开的核心规则 1. **递归展开与停止条件** 预处理器递归展开宏,但遇到**当前正在展开的宏名**时会停止。例如: ```c #define A B #define B A ``` 此时`A`展开为`B`后停止,避免无限递归[^1][^2]。 2. **延迟展开技巧** 使用中间层宏强制二次展开: ```c #define CONCAT(a, b) a##b #define CONCAT_DELAYED(a, b) CONCAT(a, b) // 中间层 ``` 此时`CONCAT_DELAYED(1, 2)`会正确生成`12`,而直接使用`CONCAT`可能因展开顺序导致错误[^1]。 #### 三、参数传递的特殊场景 1. **嵌套参数中的宏** 参数中的宏会优先展开: ```c #define SQUARE(x) ((x)*(x)) #define PRINT_SQ(x) printf("Square: %d", SQUARE(x)) ``` 当调用`PRINT_SQ(2+3)`时,实际展开为`((2+3)*(2+3))`。 2. **可变参数嵌套** 结合`__VA_ARGS__`实现灵活参数传递: ```c #define LOG(fmt, ...) printf("[LOG] " fmt, __VA_ARGS__) #define DEBUG_LOG(...) LOG("%s:%d | ", __FILE__, __LINE__), LOG(__VA_ARGS__) ``` 注意可变参数末尾需保留逗号避免语法错误[^3]。 #### 四、关键注意事项 1. **作用域与覆盖** ```c #undef PI // 取消已有定义 #define PI 3.14 // 重新定义 ``` 被取消的宏可以重新定义,但未取消的重复定义可能引发警告[^2]。 2. **符号粘连问题** 使用`##`时需注意展开顺序: ```c #define VAR(name) var_##name #define MAKE_VAR(num) VAR(num) // 需要中间层保证##正确粘连 ``` 3. **编译器差异** - GCC支持`##__VA_ARGS__`扩展(用于0参数场景) - MSVC需要启用`/Zc:preprocessor`兼容模式 不同编译器对嵌套宏的展开细节可能有差异[^1][^3]。 #### 五、典型问题解决示例 **问题:** 如何实现宏`MAX`的嵌套扩展? **方案:** ```c #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MAX3(a, b, c) MAX(MAX(a, b), c) // 嵌套调用 ``` 此时`MAX3(5, 2, 9)`将展开为两层`MAX`比较。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值