一种众所周知且可移植的方法来抑制有关未使用变量的C编译器警告(参见unused parameter warnings in C code):
#define UNUSED(x) (void)(x)
我正在寻找一种方法来概括它以获取多个输入(不同类型):
void foo(int a, long b, void* c){
/* Want this: */
ALL_UNUSED(a, b, c);
/* instead of: */
UNUSED(a);
UNUSED(b);
UNUSED(c);
}
似乎可以解决的一种方法是使用可变参数函数
static inline void ALL_UNUSED(int dummy, ...) {}
但是,我怀疑这种解决方案在专家眼中是令人反感的。
是否有符合标准且可移植(即不使用__attribute__((unused))
)方式来制作可变参数UNUSED()函数/宏?非常感谢!
修改
在C99或C预处理器的上下文中,似乎没有一种干净的方法可以满足我的要求。这就是生活。
在下面的回答中,@ Dabo展示了一种非常有趣的方式来做我要求使用的一系列宏。这是整洁和翔实的(至少对我来说),所以我接受这个答案。也就是说,我不会将它部署在一个大型项目中,因为它的分析足以超过它带来的好处(在我看来)。但人们会在这里得出不同的结论。
如下所述,使用空可变参数函数的方法也不完美。虽然它是一个非常优雅的单行,但它会引发关于单元化变量的警告(如果是的话)。此外,你必须相信你的编译器完全优化它,我原则上反对,但我尝试过的所有编译器实际上都是这样做。
一个相关案例是在早期高级接口设计阶段之后存根功能。那么你未使用的变量都将是函数参数并按定义进行初始化,以下方法可以正常工作
static inline void UNUSED(int dummy, ...) {}
void foo(int a, long b, void* c){
UNUSED(a, b, b); /* No warnings */
}
答案 0 :(得分:9)
根据这两个帖子Variadic macro to count number of arguments和Overloading macros我做了以下
#define UNUSED1(x) (void)(x)
#define UNUSED2(x,y) (void)(x),(void)(y)
#define UNUSED3(x,y,z) (void)(x),(void)(y),(void)(z)
#define UNUSED4(a,x,y,z) (void)(a),(void)(x),(void)(y),(void)(z)
#define UNUSED5(a,b,x,y,z) (void)(a),(void)(b),(void)(x),(void)(y),(void)(z)
#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5, N,...) N
#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1)
#define ALL_UNUSED_IMPL_(nargs) UNUSED ## nargs
#define ALL_UNUSED_IMPL(nargs) ALL_UNUSED_IMPL_(nargs)
#define ALL_UNUSED(...) ALL_UNUSED_IMPL( VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__ )
可以使用的内容如下
int main()
{
int a,b,c;
long f,d;
ALL_UNUSED(a,b,c,f,d);
return 0;
}
eclipse宏扩展给出:
(void)(a),(void)(b),(void)(c),(void)(f),(void)(d)
使用gcc -Wall
编译而没有警告
修改强>
#define UNUSED1(z) (void)(z)
#define UNUSED2(y,z) UNUSED1(y),UNUSED1(z)
#define UNUSED3(x,y,z) UNUSED1(x),UNUSED2(y,z)
#define UNUSED4(b,x,y,z) UNUSED2(b,x),UNUSED2(y,z)
#define UNUSED5(a,b,x,y,z) UNUSED2(a,b),UNUSED3(x,y,z)
<强> EDIT2 强>
对于您发布的inline
方法,快速测试
int a=0;
long f,d;
ALL_UNUSEDINLINE(a,f,&d);
发出‘f’ is used uninitialized in this function [-Wuninitialized]
警告。所以这里至少有一个用例打破了这种方法的普遍性
答案 1 :(得分:3)
您如何看待这个:
#define UNUSED(...) [__VA_ARGS__](){};
示例:
void f(int a, char* b, long d)
{
UNUSED(a, b, d);
}
应该扩展为lambdas定义:
[a,b,d](){}; //optimized by compiler (I hope!)
=====经过http://gcc.godbolt.org测试===== 我尝试过这段代码:
#define UNUSED(...) [__VA_ARGS__](){};
int square(int num, float a) {
UNUSED(a);
return num * num;
}
结果输出(使用-O0 -Wall编译)是:
square(int, float):
pushq %rbp
movq %rsp, %rbp
movl %edi, -4(%rbp)
movss %xmm0, -8(%rbp)
movl -4(%rbp), %eax
imull -4(%rbp), %eax
popq %rbp
ret
修改强>
如果你可以使用C ++ 11,这可能是一个更好的解决方案:
template <typename ...Args>
void UNUSED(Args&& ...args)
{
(void)(sizeof...(args));
}
答案 2 :(得分:2)
我采用了Dabo(https://stackoverflow.com/a/23238813/5126486)非常棒的解决方案并进行了一些改进,因此更容易扩展到5以上:
#define UNUSED1(a) (void)(a)
#define UNUSED2(a,b) (void)(a),UNUSED1(b)
#define UNUSED3(a,b,c) (void)(a),UNUSED2(b,c)
#define UNUSED4(a,b,c,d) (void)(a),UNUSED3(b,c,d)
#define UNUSED5(a,b,c,d,e) (void)(a),UNUSED4(b,c,d,e)
#define UNUSED6(a,b,c,d,e,f) (void)(a),UNUSED5(b,c,d,e,f)
#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5, N,...) N
#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1)
#define ALL_UNUSED_IMPL_(nargs) UNUSED ## nargs
#define ALL_UNUSED_IMPL(nargs) ALL_UNUSED_IMPL_(nargs)
#define ALL_UNUSED(...) ALL_UNUSED_IMPL( VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__ )
答案 3 :(得分:0)
这是一种非常简单的方法,不需要任何特殊技巧,也不会产生任何运行时开销。
原始答案(仅限 C++)
#define UNUSED(...) (void)sizeof(__VA_ARGS__)
https://godbolt.org/z/Gz8MfvaTz
更新答案(C 和 C++)
我忘记将编译器从 C++ 更改为 C,因此修改了答案。
int main(int argc, char ** argv)
{
/* different types */
UNUSED(argc, argv);
/* many variables */
int w, x, y, z;
UNUSED(w, x, y, z);
/* single variable */
void * ptr;
UNUSED(ptr);
}
MSVC
/O2 /W4
没有来自 C 和 C++ 编译器的警告。
叮当声
-O3 -Wall -Wextra
没有来自 C 和 C++ 编译器的警告。
海湾合作委员会
-O3 -Wall -Wextra
只有 C++ 编译器没有警告。
对于 C 编译器,只忽略最后一个参数而不发出警告。因此,在最坏的情况下,此版本的 UNUSED
与传统的 #define UNUSED(x) ((void)x)
相当。
答案 4 :(得分:-1)
您可以使用编译时间__VA_ARGS__
宏。
#define UNUSED(...) (void)(__VA_ARGS__)
更新:经过大量试验,我找到了一个优化的解决方案:
#define UNUSED(...) __VA_ARGS__
int main()
{
int e, x;
char **a, **b, *c, d[45];
x = x, UNUSED(a, b, c, d, e), x;
return 0;
}
注意:
它不会完全消除警告,但会将减少<{1}}相同类型的警告:
3
第一个和最后一个warning: value computed is not used
确保分配相同的数据类型。
我会说它已经过优化,因为对于任意数量的未使用变量,它会发出x
警告(我可能错了,请自行测试,如果你得到更多就报告我)和数量实现它所需的代码(MACRO操作)更少。
我仍在努力,如果我找到更好的解决方案,我会发布。