c/c++语言开发共享宏评估订单


可能重复:
宏中的#和##

为什么第二个printf的输出是f(1,2)什么是宏的评估顺序?

#include  #define f(a,b) a##b #define g(a) #a #define h(a) g(a) int main() { printf("%sn",h(f(1,2))); printf("%sn",g(f(1,2))); return 0; } output 12 f(1,2) 

    来自https://gcc.gnu.org/onlinedocs/cpp/Argument-Prescan.html#Argument-Prescan

    宏参数在被替换为宏体之前是完全宏扩展的,除非它们被字符串化或粘贴到其他标记。 替换后,将再次扫描整个宏体(包括替换参数),以便扩展宏。 结果是参数被扫描两次以扩展其中的宏调用。

    含义:

    h(f(1,2)) -> g(12) -> "12"

    g(f(1,2)) -> "f(1,2)"

    参数在被替换到替换列表之前被宏替换, 除非它作为# (stringize)或## (concatenate)的操作数出现。

    在宏h ,参数a不是这两个运算符之一的参数,因此参数被宏替换,然后替换为替换列表。 也就是说,参数f(1,2)被宏替换为1##2 ,然后是12 ,然后它被代入g(12) ,这被(再次)宏替换成"12"

    当你直接调用g ,参数a #运算符的参数,所以它的参数在替换之前不会被宏替换: f(1,2)直接替换到替换列表中,产生"f(1,2)"

    我不确定评估顺序对于C或C ++宏来说是一个有意义的术语,因为宏扩展发生在编译时

    至于为什么第二个输出是f(1,2)是因为宏是文本替换。 当g(f(1,2))被展开时, g自变量是标记f(1,2)的序列并且被字符串化。

    考虑C编译器。 在第二个printf的上下文中,它读取一个g令牌, 在lexing&parsing时识别它是一个宏然后扩展该宏调用。 编译器基本上是这样做的:如果当前令牌是一个宏名称,那么在lexing你的代码时展开它。 宏扩展只在可能的情况下发生(因此对于带参数的宏需要左括号),并尽快完成。

      以上就是c/c++开发分享宏评估订单相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/572046.html

      (0)
      上一篇 2021年3月3日
      下一篇 2021年3月3日

      精彩推荐