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

时间:2017-01-17 09:29:38

标签: c++ macos qt

// 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 with msvc2010),但当我尝试在macOS下编译它时(带有clang的Qt),我收到错误:::

  

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

如何在macOS下使其工作,还是有另一种方法来执行相同的功能?

1 个答案:

答案 0 :(得分: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 ;
}