Variadic UNUSEDfunction/宏

抑制C编译器有关未使用变量的警告的一种众所周知的可移植方法是(参见C代码中未使用的参数警告 ):

#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展示了一种非常有趣的方式来做我要求使用的一系列宏。 这是整洁和翔实的(至少对我而言),所以我接受了这个答案。 也就是说,我不会将它部署在一个大型项目中,因为它的篇幅足以超过它带来的好处(在我看来)。 但人们会在这里得出不同的结论。

如下所述,使用空可变参数函数的方法也不完美。 虽然它是一个非常优雅的单行,但它会引发关于单元化变量的警告(如果它们是)。 此外,你必须相信你的编译器完全优化它,我原则上反对,但我尝试过的所有编译器实际上都是这样做的。

一个相关的情况是在早期高级接口设计阶段之后存根function。 然后你未使用的变量都将是函数参数并按定义初始化,以下方法可以正常工作

 static inline void UNUSED(int dummy, ...) {} void foo(int a, long b, void* c){ UNUSED(a, b, b); /* No warnings */ } 

基于这两个postVariadic宏来计算参数的数量 ,并且重载宏我做了以下

 #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]警告中'f' is used uninitialized in this function [-Wuninitialized] 。 所以这里至少有一个用例打破了这种方法的普遍性

你怎么看待这件事:

 #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  void UNUSED(Args&& ...args) { (void)(sizeof...(args)); } 

我采用了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__ ) 

您可以使用编译时__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

  2. 第一个和最后一个x确保分配相同的数据类型。

  3. 我会说它已经过优化,因为对于任意数量的未使用的变量,它会发出3警告(我可能错了,请自己测试,如果你得到更多就报告我),并且实现它所需的代码量(MACRO操作)是减。

  4. 我还在努力,如果我找到更好的解决方案,我会发布。