【问题标题】:Unexpected predefined macro behaviour when pasting tokens粘贴标记时出现意外的预定义宏行为
【发布时间】:2010-08-15 15:33:05
【问题描述】:

以下(用gcc -E blah.c测试):

#define UNUSED(type) type UNUSED_ ## __COUNTER__
UNUSED(char const *)
UNUSED(int)

生成:

char const * UNUSED__COUNTER__
int UNUSED__COUNTER__

我期待:

char const * UNUSED0
int UNUSED1

我尝试调用另一个宏,将参数括在括号中,但无济于事。 如果我不粘贴令牌,它似乎工作正常。 documentation 特别提到了在令牌粘贴中使用__COUNTER__

我做错了什么?

【问题讨论】:

    标签: c gcc


    【解决方案1】:

    使用 gcc 4.4 进行实验,这可行:

    #define UNUSED(type) UNUSED_(type, __COUNTER__)
    #define UNUSED_(type, counter) UNUSED__(type, counter)
    #define UNUSED__(type, counter) type UNUSED_ ## counter
    UNUSED(char const *)
    UNUSED(int)
    

    但是我连中级都拿出来也行不通。

    【讨论】:

      【解决方案2】:

      __COUNTER__ 仅在GCC 4.3 中引入 - 如果您碰巧使用早期版本,则根本没有定义宏。在这种情况下,Boost.PPsBOOST_PP_COUNTER 宏可能值得研究。

      在较新的 GCC 版本上,您仍然需要不同的连接方法,因为## 会阻止其参数扩展。因此,在使用 ## 之前,您必须先扩展它们:

      #define CAT(a, b) CAT_I(a, b)
      #define CAT_I(a, b) CAT_II(a ## b)
      #define CAT_II(x) x
      #define UNUSED(type) type CAT(UNUSED_, __COUNTER__)
      

      如果您已经在使用 Boost,BOOST_PP_CAT() 会为您提供相同的功能。

      【讨论】:

      • 抱歉 C++ 标签不正确,所以将 cpp 更改为 c++...显然有人没有听说过 C 预处理器
      • @Matt:C 和 C++ 的答案是一样的,甚至 Boost.PP 都适用。
      • 我的意思是像 Boost 这样的 C++ 语言在这里没有用处。但感谢您提供的信息。
      【解决方案3】:

      我相信你必须“双重扩展”它:

      #define STR(x)    #x
      #define UNUSED(type) type UNUSED_ ## STR(__COUNTER__)
      UNUSED(char const *) 
      UNUSED(int) 
      

      【讨论】:

      • 运气不好:char const * UNUSED_STR(0)int UNUSED_STR(1)
      • UNUSED_后的空格是问题吗?
      • 你肯定不是要字符串化,对吗?如果这完全有效,它会产生类似char const * UNUSED"0"...
      猜你喜欢
      • 2021-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-05
      • 1970-01-01
      • 1970-01-01
      • 2015-10-10
      相关资源
      最近更新 更多