C预处理器删除尾随逗号

Cin*_*air 13 c gcc c-preprocessor

我有一个像这样的宏:

#define C( a... ) ( char *[] ){ a, 0 }
Run Code Online (Sandbox Code Playgroud)

这适用于非空参数:

C( "a", "b" ) => ( char *[] )( "a", "b", 0 }
Run Code Online (Sandbox Code Playgroud)

但是我想在提供空参数时删除尾随逗号:

C() => ( char *[] ){ , 0 }
Run Code Online (Sandbox Code Playgroud)

这可能吗?

cxw*_*cxw 5

至少在 GCC 5.4.0 中,在 Cygwin (默认-std=gnu11)上,这似乎可以满足您的要求(假设我正确理解您的问题):

#define C( a... ) ( char *[] ){ a 0 }
                                 ^ no comma!    
C( "a", "b", ) 
           ^ comma here
=> ( char *[] )( "a", "b", 0 }

C() 
=> ( char *[] ){ 0 }
Run Code Online (Sandbox Code Playgroud)

使用gcc -E且未使用其他命令行选项进行测试。

编辑正如@KerrekSB 指出的,这是不可移植的。GCC 预处理器文档有这样的说法(强调):

对于唯一的宏参数是可变参数参数的情况,上面的解释是不明确的[如在这种情况下-Ed.],因为尝试区分根本没有参数是空参数还是丢失参数是没有意义的。在这种情况下,C99 标准明确指出必须保留逗号,但是现有的 GCC 扩展用来吞掉逗号。因此,当符合特定的 C 标准时,CPP 会保留逗号,否则会删除它。

所以上面的代码在 GCC 中工作得很好,但在其他编译器上可能不行。然而,它确实对我有用gcc -std=c90 -E(或c99, 或c11)。


use*_*037 5

查看可在可变参数宏__VA_OPT__()中使用的 GCC 函数宏。

#define C(...) (char *[]) { __VA_ARGS__ __VA_OPT__(,) 0 }

C("a", "b");   expands to (char *[]) { "a", "b" , 0 };
C();           expands to (char *[]) { 0 };
Run Code Online (Sandbox Code Playgroud)

传递给的参数仅在非空__VA_OPT__()时才会扩展。__VA_ARGS__