我使用variadic宏来模拟默认参数。我用-Wunused-value
编译。因此,我收到以下警告:
warning: left-hand operand of comma expression has no effect
有没有办法以某种方式修复此警告而无需删除-Wunused-value
?或者我必须最终使用#pragma GCC diagnostic ignored "-Wunused-value"
?
#include <stdio.h>
#define SUM(a,...) sum( a, (5, ##__VA_ARGS__) )
int sum (int a, int b)
{
return a + b;
}
int main()
{
printf("%d\n", SUM( 3, 7 ) );
printf("%d\n", SUM( 3 ) );
}
答案 0 :(得分:1)
您使用的##
构造是gcc专业而非便携式。不要使用它,还有其他方法。
以下内容应该符合您的期望
#define SUM2(A, B, ...) sum((A), (B))
#define SUM1(...) SUM2(__VA_ARGS__)
#define SUM(...) SUM1(__VA_ARGS__, 5, 0)
许多人不赞成使用宏默认参数的游戏,因为它们可能会使代码更难以阅读。 目前我建议您不要在程序中使用此类构造。在进入这些深奥的东西之前,你应该学习更多基础知识。
你想要使编译器静音的想法真的很糟糕。编译器可以帮助你,听取他的意见。相反,将警告级别提高到最大值并改进代码,直到它编译而没有任何警告。
答案 1 :(得分:0)
Jens Gustedt提出了一个非常好的针对特定问题的便携式解决方案。我不知道,,##__VA_ARGS__
是GCC扩展名(也许还有Clang吗?)。但是,有针对作者最初意图的GCC解决方案。
作为特定于问题且非常特定于GCC的解决方案,您可以使用_Pragma("GCC diagnostic ignored \"-Wunused-value\"")
并在宏扩展周围定界。这将保持可读性。这并非在所有地方都有效。它主要在无法应用这些编译指示的函数外部的静态初始值设定项列表中失败。我确实在此类初始化程序列表中寻找解决方案,因为找不到任何隐藏读者警告语用语的方法。除此之外,例如对于sum()
之类的函数调用(我认为仅在函数体本身中有效),可以使用它:
#define SUM(a,...) ({\
_Pragma("GCC diagnostic push")\
_Pragma("GCC diagnostic ignored \"-Wunused-value\"")\
sum( a, (5, ##__VA_ARGS__) );\
_Pragma("GCC diagnostic pop")\
})
请记住,您只能在函数体内以及需要表达式的地方使用它。宏扩展后,警告将保持打开状态。
但是我找到了一个通用的解决方案!借助,##__VA_ARGS__
功能,可以进行条件宏扩展。它提供了基于参数空白的条件扩展功能。
此功能不一定会增加预处理器的替代功能。如果您使用的参数中包含逗号,例如(<...>)
表示false或0,而(<...>,<...>)
表示true或1,则可以实现相同的效果。但是只有条件逗号允许您舒适地基于参数的空白来进行条件扩展。
请参阅:您可能无需编写SUM(A)
就可以将sum((A),5)
扩展为##__VA_ARGS__
来编写代码,但是您可能无法编写将SUM(,B)
扩展为{{1 }}。但是您可以使用sum((somevalue),B)
来做到这一点。
示例:
##__VA_ARGS__
没有条件逗号,您只能根据参数的数量或预定义的级联有条件地进行扩展,但是通过这种方式,您可以将任何单个未定义的符号用作条件。
PS:循环呢? C语言中的宏被设计为有限的,以加快编译速度。由于循环周期的限制取决于源代码的大小,因此不会出现无限循环。有限的循环是唯一阻碍您完成图景完整性的事情,但是实际的实际计算机科学问题(与嵌入式或操作系统不同)不需要无限循环来进行计算。它们都受问题大小的限制。图灵机还使用符号的有限字母。您可能知道最坏情况下所需的循环次数限制,并且可以在可变长度的宏参数列表上创建运行功能性循环(“减少”或“过滤器”宏),从而可以重新格式化宏参数列表做魔术。唯一的要求是逗号。您不能在元素之间没有逗号的情况下对其进行迭代。