关于 C 宏无效预处理令牌的错误

Posted

技术标签:

【中文标题】关于 C 宏无效预处理令牌的错误【英文标题】:error about C macro invalid preprocessing token 【发布时间】:2017-01-17 09:29:38 【问题描述】:
// define the macro
#define FATAL(S,...) qDebug("%s,%s,%d,%s:"##S,"[scribble]",__FILE__,__LINE__,__FUNCTION__,##__VA_ARGS__)
// call the macro
FATAL("not supported commandid:%d",cmdid);

虽然此代码在 Windows 下工作(Qt 与 msvc2010),但当我尝试在 macOS 下编译它(Qt 与 clang)时,我收到错误:::

粘贴形成的 "%s,%s,%d,%s:""不支持 commandid:%d",无效 预处理令牌。

如何让它在 macOS 下工作,或者有其他方法可以实现相同的功能吗?

【问题讨论】:

我宁愿把宏定义为#define FATAL(S,...) qDebug("[scribble],%s,%d,%s:" S,__FILE__,__LINE__,__FUNCTION__,##__VA_ARGS__)见example 【参考方案1】:

标记## 放在逗号和变量参数之间时,只有表示可选参数的特殊含义:, ##__VA_ARGS__

这是对 C 语言的扩展。

在你的例子中,第二个参数是正确的,但不是第一个。

如果您不需要第一个参数是可选的,只需删除标记##:

#define FATAL(S,...) printf("%s,%s,%d,%s:"S,    \
                     "[scribble]",__FILE__,__LINE__,__FUNCTION__,##__VA_ARGS__)

但第一个参数也可以是可选的,使用另一个宏来扩展字符串文字和第一个参数,同时使第一个参数可选:

#include <stdlib.h>
#include <stdio.h>

#define MERGE_EXPAND( a , ... )   a __VA_ARGS__
#define MERGE( a , ... )          MERGE_EXPAND( a , ##__VA_ARGS__ )

#define FATAL(S,...)              printf( MERGE( "%s,%s,%d,%s:",S),  \
                                  "[scribble]",__FILE__,__LINE__,__FUNCTION__,##__VA_ARGS__)

int main( void )

    int cmdid = 12345;

    FATAL();    
    puts( "" ) ;
    FATAL( "first argument" );
    puts( "" ) ;
    FATAL( "first and second arguments: %d" , cmdid );

    return EXIT_SUCCESS ;

【讨论】:

非常感谢。很强大。 另一个问题,为什么它不能在macos下工作,而是在windows下工作。 @Gavin Visual Studio 以不同的方式处理这个问题。

以上是关于关于 C 宏无效预处理令牌的错误的主要内容,如果未能解决你的问题,请参考以下文章

配置 AccessDeniedHandler 以处理无效的 csrf 令牌

C语言宏定义

获取新的访问令牌以处理过期的访问令牌时,grant_type 参数无效或参数丢失

为啥将宏参数放在括号中会导致错误? [关闭]

如何在rails中处理来自应用程序控制器的无效真实性令牌json请求

无效的 Facebook 令牌