Вариативная неиспользуемые функции/макроса

известный и портативный способ подавления предупреждений компилятора 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))) способ сделать вариативным неиспользованный() функция/макрос? Большое спасибо!

редактировать

кажется, не существует чистого способа сделать то, что я просил в контексте C99 или препроцессора C. Такова жизнь.

в своем ответе ниже @Dabo показывает довольно интересный способ сделать то, что я просил, используя серию макросов. Это аккуратно и информативно (по крайней мере для меня), поэтому я принимаю это ответ. Тем не менее, я бы не стал развертывать его в большом проекте, потому что он достаточно слезлив, чтобы перевесить пользу, которую он приносит (в моих глазах). Но здесь люди придут к разным выводам.

как отмечено ниже, подход к использованию пустой вариационной функции также не идеален. Хотя это довольно элегантный однострочный, он будет провоцировать предупреждения о unititialized переменных (если они есть). Кроме того, вы должны доверять своему компилятору, чтобы полностью оптимизировать его, что я возражаю в принцип, но все компиляторы, с которыми я пробовал, действительно делают.

один уместный случай когда stubbing функции после предыдущего высокопоставленного участка конструкции интерфейса. Тогда ваши неиспользуемые переменные будут аргументами функции и инициализированы по определению, и следующий подход отлично работает

static inline void UNUSED(int dummy, ...) {}

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

4 ответов


на основе этих двух сообщений Variadic макрос для подсчета количества аргументов и перегрузка макросов я сделал следующее

#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 без предупреждений

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

как inline метод, который вы выложили, быстрый тест

int a=0;
long f,d;

ALL_UNUSEDINLINE(a,f,&d);

дает ‘f’ is used uninitialized in this function [-Wuninitialized] предупреждение. Так вот хотя бы один прецедент, который нарушает общность этого aproach


что вы думаете об этом:

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

пример:

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

должно быть расширено объявление определение лямбда:

[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

EDIT:

если вы можете использовать C++11, это может быть лучшим решением :

template <typename ...Args>
void UNUSED(Args&& ...args)
{
    (void)(sizeof...(args));
}

Я взял Дабо (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 предупреждения (я могу ошибаться, пожалуйста, проверьте его самостоятельно и сообщите мне, если вы получите больше), а количество кода (макро-манипуляции), необходимое для его достижения, меньше.

  4. Я все еще работаю над этим, опубликую, если я достигну лучшего решения.