Variadic UNUSED function/macro

后端 未结 4 1117
陌清茗
陌清茗 2021-02-04 11:25

A well-known and portable way to suppress C compiler warnings about unused variables is (see unused parameter warnings in C code):

#define UNUSED(x) (void)(x)


        
相关标签:
4条回答
  • 2021-02-04 12:01

    Based on these two posts Variadic macro to count number of arguments, and Overloading macros i made the following

    #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__ )
    

    what can be used as follows

     int main()
     {
        int a,b,c;
        long f,d;
    
        ALL_UNUSED(a,b,c,f,d);
    
        return 0;
      }
    

    eclipse macro expansion gives :

      (void)(a),(void)(b),(void)(c),(void)(f),(void)(d)
    

    compiled with gcc -Wall with no warnings

    EDIT:

    #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

    As for inline method you posted, a quick test

    int a=0;
    long f,d;
    
    ALL_UNUSEDINLINE(a,f,&d);
    

    gives ‘f’ is used uninitialized in this function [-Wuninitialized] warning. So here at least one use case which breaks generality of this aproach

    0 讨论(0)
  • 2021-02-04 12:15

    I took Dabo's (https://stackoverflow.com/a/23238813/5126486) awesome solution and improved a little bit so it's easier to extend to more than 5:

    #define UNUSED0()
    #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 VA_NUM_ARGS_IMPL(_0,_1,_2,_3,_4,_5, N,...) N
    #define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL(100, ##__VA_ARGS__, 5, 4, 3, 2, 1, 0 )
    
    #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__ )
    
    0 讨论(0)
  • 2021-02-04 12:16

    You can use compile time __VA_ARGS__ macro.

    #define UNUSED(...) (void)(__VA_ARGS__)

    UPDATE: After lot of trials, I came up to an optimized solution:

    #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;
    }
    

    NOTES:

    1. It doesn't eliminate warnings completely but reduces them to just 3 same type of warnings:
      warning: value computed is not used

    2. The first and last x ensure assignment of same datatypes.

    3. I will say it is optimized because for any number of unused variables it gives 3 warnings (I may be wrong, please test it yourself and do report me if you get more) and the amount of code (MACRO manipulations) required to achieve it is less.

    4. I am still working on it, will post if I reach to any better solution.

    0 讨论(0)
  • 2021-02-04 12:19

    What do you think about this:

    #define UNUSED(...) [__VA_ARGS__](){};
    

    Example:

    void f(int a, char* b, long d)
    {
        UNUSED(a, b, d);
    }
    

    Should be expanded ad a lambdas definition:

    [a,b,d](){}; //optimized by compiler (I hope!)
    

    ===== Tested with http://gcc.godbolt.org ===== I've tryed with this code:

    #define UNUSED(...) [__VA_ARGS__](){};
    
    int square(int num, float a) {
      UNUSED(a);
      return num * num;
    }
    

    The resulting output (compiled with -O0 -Wall) is:

    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
    

    EDIT:

    If you can use C++11 this could be a better solution :

    template <typename ...Args>
    void UNUSED(Args&& ...args)
    {
        (void)(sizeof...(args));
    }
    
    0 讨论(0)
提交回复
热议问题