可变宏编译错误

VARIADIC MACRO compile error

本文关键字:错误 编译      更新时间:2023-10-16

我想学习如何使用宏。

我只是写了一个示例,但未能在我的本地g++4.9上编译

#define P(...) printf("13", ##__VA_ARGS__)
int main() {
// your code goes here
P();
return 0;
}

我将得到如下编译错误

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In function 'int main()':
main.cpp:4:42: error: expected primary-expression before ')' token
 #define P(...) printf("13", ##__VA_ARGS__)
                                          ^
main.cpp:7:5: note: in expansion of macro 'P'
     P();
     ^

但是同样的代码可以在ideone....上编译http://ideone.com/ucEXXz

和VS2015。

对此有什么合理的解释吗?

如何为所有编译器编写一个可移植的宏....

谢谢。

在C中,接受变量参数的函数需要一个原型声明,而在c++中,所有函数都需要一个原型。printf的声明见stdio.h

#include <stdio.h>
#define P(...) printf("13", ##__VA_ARGS__)
int main() {
P();
return 0;
}

##__VA_ARGS__语法不规范。这是一个由GCC实现的"吞逗号,如果__VA_ARGS__是空的"扩展,并且似乎已被其他编译器采用。

关于-std=c++14的行为:

编译器可以接受几种基本标准,如' c90 '或' c++98 ',以及这些标准的GNU方言,如' gnu90 '或' GNU ++98 '。当指定了基本标准后,编译器接受所有遵循该标准的程序以及那些使用与该标准不冲突的GNU扩展的程序。例如,-std=c90关闭与ISO c90不兼容的GCC的某些特性,例如asm和typeof关键字,但不关闭在ISO c90中没有意义的其他GNU扩展,例如省略?:表达式的中间项。
-std=的GCC文档

##__VA_ARGS__扩展名与标准不冲突。导致它被coliru站点拒绝的原因是设置了-pedantic标志。

有效的ISO C和ISO c++程序在使用或不使用此选项时应该正确编译(尽管极少数需要-ansi或-std选项来指定所需的ISO C版本)。然而,如果没有此选项,某些GNU扩展和传统的C和c++特性也会被支持。使用此选项,它们将被拒绝。
-pedantic的GCC文档