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

error about C macro invalid preprocessing token

本文关键字:预处理 令牌 无效 错误 关于      更新时间:2023-10-16
// 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 with clang),我得到了错误::

粘贴格式为"%s,%s,%d,%s:"的命令ID不受支持:%d,无效预处理令牌。

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

标记##只有在逗号和变量参数之间时才具有指示可选参数的特殊含义:, ##__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 ;
}