Як придушити попередження "невикористаного параметра" в C?


210

Наприклад:

Bool NullFunc(const struct timespec *when, const char *who)
{
   return TRUE;
}

У мові C ++ я зміг помістити /*...*/коментар навколо параметрів. Але не в С, звичайно, де це дає мені помилку error: parameter name omitted.



4
@CiroSantilli Це питання має більше відгуків, інше питання було б краще позначити як повторне.
sashoalm


-Wno-unused-parameter, це занадто шумно і рідко ловить помилок esp. коли -Wshadowвикористовується.
Trass3r

Відповіді:


297

Я зазвичай пишу такий макрос:

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

Ви можете використовувати цей макрос для всіх невикористаних параметрів. (Зверніть увагу, що це працює на будь-якому компіляторі.)

Наприклад:

void f(int x) {
    UNUSED(x);
    ...
}

45
Я просто використовую (пустоту) x безпосередньо
проф. Фолкен

6
в той час як це єдиний портативний спосіб AFAIK, роздратування з цього приводу полягає в тому, що він може ввести в оману, якщо використовувати змінну пізніше і забути ro видалити невикористаний рядок. ось чому невикористані GCC є приємними.
ideaman42

6
@CookSchelling: Ах, але ти не повинен його використовувати так. Зробіть що - щось на зразок цього: void f(int x) {UNUSED(x);}.
Робота

9
@Alcott тому, що (як у моєму випадку) функція може бути однією з багатьох, які повинні мати однаковий підпис, оскільки на них посилається вказівник функції.
Джош

17
Я використовую, #define UNUSED(...) (void)(__VA_ARGS__)що дозволяє застосувати це до кількох змінних.
Меттью Мітчелл

110

У gcc можна позначити параметр unusedатрибутом .

Цей атрибут, прикріплений до змінної, означає , що змінна призначається , щоб бути , можливо , чи не використовується. GCC не видасть попередження для цієї змінної.

На практиці це досягається введенням __attribute__ ((unused))безпосередньо перед параметром. Наприклад:

void foo(workerid_t workerId) { }

стає

void foo(__attribute__((unused)) workerid_t workerId) { }

24
Для будь-яких новачків, як я, це означає ставити __attribute__ ((unused))перед аргументом.
Джош

2
@josch Я думаю, ви абсолютно правильні, але, здається, документація передбачає, що його слід ставити після параметра. Обидва варіанти, ймовірно, підтримуються без проблем.
Антоніо

Також зауважте, що __attribute__((unused))це власне розширення GCC . Він підтримується деякими іншими компіляторами, але я припускаю, що це не буде працювати з MSVC. Однак це безпосередньо не є частиною стандарту компілятора, тому це не так портативно, як деякі інші параметри
Zoe

58

Ви можете використовувати невикористовуваний атрибут gcc / clang, однак я використовую ці макроси в заголовку, щоб уникнути наявності специфічних атрибутів gcc по всьому джерелу, а також наявність __attribute__скрізь є трохи довершеною / негарною.

#ifdef __GNUC__
#  define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
#else
#  define UNUSED(x) UNUSED_ ## x
#endif

#ifdef __GNUC__
#  define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x
#else
#  define UNUSED_FUNCTION(x) UNUSED_ ## x
#endif

Тоді ви можете зробити ...

void foo(int UNUSED(bar)) { ... }

Я вважаю за краще це, тому що ви отримуєте помилку, якщо намагаєтесь використовувати barкод у будь-якому місці, щоб ви не могли залишити атрибут помилково.

а для функцій ...

static void UNUSED_FUNCTION(foo)(int bar) { ... }

Примітка 1):
Наскільки мені відомо, MSVC не має еквіваленту __attribute__((__unused__)).

Примітка 2): макрос не буде працювати на аргументи , які містять круглі дужки, тому якщо у вас є аргумент , як ви не можете зробити, або , це єдиний недолік в макро я знайшов до сих пір, в цих випадках , я падаю назад до
UNUSED
float (*coords)[3]
float UNUSED((*coords)[3])float (*UNUSED(coords))[3]UNUSED(void)coords;


Чи, можливо, лише #define __attribute__(x)для середовищ, що не належать до GCC (AFAIK жоден із цих програм __attribute__не підтримується MSVC)?
Франклін Ю

Це може спрацювати, але вбудовані префіксні умови зарезервовані для компілятора, тому я б краще цього уникнути.
ideaman42

Для мого gcc принаймні ставити специфікатор атрибутів до того, як ідентифікатор, здається, працює як для функцій, vars, так і параметра, тож щось на зразок #define POSSIBLY_UNUSED (ідентифікатор) атрибут __ ((__ не використовується )) ідентифікатор можна використовувати для всіх трьох
Бріттон Керін

Коли викладаю його після отримання warning: unused parameter ‘foo’ [-Wunused-parameter](gcc 7.3.0)
ideaman42

19

З gcc з невикористаним атрибутом:

int foo (__attribute__((unused)) int bar) {
    return 0;
}

16

Бачачи, що це позначено як gcc, ви можете використовувати перемикач командного рядка Wno-unused-parameter.

Наприклад:

gcc -Wno-unused-parameter test.c

Звичайно, це впливає на весь файл (а може і на проект, залежно від місця встановлення комутатора), але вам не потрібно змінювати жоден код.


7

Специфічним способом придушення попередження про невикористаний параметр для блоку вихідного коду є додавання його до наступних заяв прагми:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
<code with unused parameters here>
#pragma GCC diagnostic pop

Clang також підтримує ці діагностичні прагги clang.llvm.org/docs/…
eush77

4

Маркування атрибуту є ідеальним способом. MACRO призводить до колись плутанини. і використовуючи void (x), ми додаємо накладні витрати на обробку.

Якщо аргумент введення не використовується, використовуйте

void foo(int __attribute__((unused))key)
{
}

Якщо не використовується змінна, визначена всередині функції

void foo(int key)
{
   int hash = 0;
   int bkt __attribute__((unused)) = 0;

   api_call(x, hash, bkt);
}

Тепер пізніше використовуйте хеш змінну для вашої логіки, але bkt не потребує. визначте bkt як невикористаний, інакше компілятор говорить'bkt set bt not used ".

ПРИМІТКА. Це лише для того, щоб придушити попередження не для оптимізації.


1
Ви не додасте жодних накладних витрат при обробці за допомогою void(x)компілятора оптимізує його.
Majora320

4

У мене така ж проблема. Я використав бібліотеку третьої частини. Коли я компілюю цю бібліотеку, компілятор (gcc / clang) поскаржиться на невикористані змінні.

Подобається це

test.cpp: 29: 11: попередження: набір змінної 'магія', але не використовується [-Замінена-але-встановлена ​​змінна] коротка магія [] = {

test.cpp: 84: 17: попередження: невикористана змінна 'before_write' [-Унікована змінна] int64_t before_write = Thread :: currentTimeMillis ();

Тож рішення досить зрозуміле. Додавання -Wno-unusedяк gcc / clang CFLAG придушить усі "невикористані" попередження, навіть думки, які ви -Wallвстановили.

Таким чином, НЕ ПОТРІБНО змінювати будь-який код.


1
Це добре, якщо ви насправді хочете ігнорувати всі невикористані попередження, але це майже ніколи не буває. Зазвичай це просто конкретні випадки, які ви хочете ігнорувати.
Ден Бешард

1

У MSVC для придушення конкретного попередження достатньо вказати його номер для компілятора як / wd #. Мій CMakeLists.txt містить такий блок:

If (MSVC)
    Set (CMAKE_EXE_LINKER_FLAGS "$ {CMAKE_EXE_LINKER_FLAGS} / NODEFAULTLIB: LIBCMT")
    Add_definitions (/W4 /wd4512 /wd4702 /wd4100 /wd4510 /wd4355 /wd4127)
    Add_definitions (/D_CRT_SECURE_NO_WARNINGS)
Elseif (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUC)
    Add_definitions (-Wall -W -pedantic)
Else ()
    Message ("Unknown compiler")
Endif ()

Зараз я не можу сказати, що саме / wd4512 / wd4702 / wd4100 / wd4510 / wd4355 / wd4127 означає, тому що я не приділяю MSVC жодної уваги протягом трьох років, але вони пригнічують суперпедантичні попередження, які не впливають на результат.


0

Я бачив, як використовується цей стиль:

if (when || who || format || data || len);

14
Гм. Я не можу сказати, що мені це подобається, оскільки це передбачає, що всі задіяні параметри можуть бути перетворені в bool.
Сума

1
Це насправді не є вдалою умовою, хоча компілятор майже напевно оптимізує це, але не дуже зрозуміло, що відбувається, і може заплутати перевіряючі статичні джерела. краще скористайтеся однією з інших пропозицій тут ІМХО.
ideaman42

1
Я не можу повірити, що я все ще отримую відповіді на це. У запитанні було зазначено, що це стосується C. Так, іншою мовою це не вийшло.
Юстін

2
Я б не використовував це, але +1 для коефіцієнта новизни.
mgalgs

2
перевірка істинності змінних може давати попередження для структур. напр. struct { int a; } b = {1}; if (b);GCC попереджає used struct type value where scalar is required.
ideaman42

-1

Для запису мені подобається відповідь Іова вище, але мені цікаво рішення просто використання імені змінної самостійно в заяві "нічого не робити":

void foo(int x) {
    x; /* unused */
    ...
}

Звичайно, у цього є недоліки; наприклад, без "невикористаної" примітки це виглядає як помилка, а не навмисний рядок коду.

Перевага полягає в тому, що не потрібно використовувати DEFINE і він позбавляється від попередження.

Чи є якісь ефективність, оптимізація чи інші відмінності?


2
Я або використовував це з MSVC, але GCC піднімає попередження "заява без ефекту". Отже, рішення Іова - це шлях.
Дмитро Семикін

Цей підхід все ще породжує попередження в
XCode
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.