Как подавить предупреждения «неиспользуемый параметр» в C?

210

Например:

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

В C ++ я смог поместить /*...*/комментарий вокруг параметров. Но не в C, конечно, где это дает мне ошибку error: parameter name omitted.

nixgadget
источник
возможный дубликат того, как лучше подавить предупреждение «Неиспользованная переменная x»
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功
4
@CiroSantilli Этот вопрос имеет больше голосов, было бы лучше пометить другой вопрос как дубликат.
sashoalm
1
См. Также версию этого вопроса
Шафик Ягмур
-Wno-unused-parameterПросто слишком шумно и редко ловит баги особенно. когда -Wshadowиспользуется.
Trass3r

Ответы:

297

Я обычно пишу такой макрос:

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

Вы можете использовать этот макрос для всех ваших неиспользуемых параметров. (Обратите внимание, что это работает на любом компиляторе.)

Например:

void f(int x) {
    UNUSED(x);
    ...
}
работа
источник
45
Я просто использую (void) x напрямую
проф. Фалькен
6
В то время как это единственный переносимый способ AFAIK, раздражение в том, что это может ввести в заблуждение, если вы позже используете переменную и забудете ro удалить неиспользуемую строку. Вот почему GCC не используется, это хорошо.
ideasman42
6
@CookSchelling: Ах, но вы не должны использовать это так. Сделайте что - то вроде этого: void f(int x) {UNUSED(x);}.
Работа
9
@Alcott, потому что (как в моем случае) функция может быть одной из многих, которые должны иметь одну и ту же сигнатуру, потому что на них ссылается указатель функции.
1915 года
17
Я использую #define UNUSED(...) (void)(__VA_ARGS__)который позволяет мне применить это к нескольким переменным.
Мэтью Митчелл
110

В gcc вы можете пометить параметр unusedатрибутом .

Этот атрибут, прикрепленный к переменной, означает, что переменная, возможно, не используется. GCC не будет выдавать предупреждение для этой переменной.

На практике это достигается путем установки __attribute__ ((unused))непосредственно перед параметром. Например:

void foo(workerid_t workerId) { }

становится

void foo(__attribute__((unused)) workerid_t workerId) { }
Flow
источник
24
Для любого новичка, такого как я, это означает ставить __attribute__ ((unused))перед аргументом.
1915 года
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;

ideasman42
источник
Или, может быть, только #define __attribute__(x)для среды без GCC (AFAIK ни один из __attribute__них не поддерживается MSVC)?
Франклин Ю
Это может сработать, но термины с префиксом dunder зарезервированы для компилятора, поэтому я бы предпочел этого избежать.
ideasman42
Для моего gcc, по крайней мере, размещение спецификатора атрибута до того, как идентификатор, кажется, будет работать правильно для функций, переменных и параметров, поэтому что-то вроде #define POSSIBLY_UNUSED (идентификатор) атрибута __ ((__ не используется )) можно использовать для всех трех
Бриттон Керин
Когда ставлю его после того, как я получаю warning: unused parameter ‘foo’ [-Wunused-parameter](gcc 7.3.0)
ideasman42
19

С gcc с неиспользованным атрибутом:

int foo (__attribute__((unused)) int bar) {
    return 0;
}
Тедди
источник
16

Видя, что это помечено как gcc, вы можете использовать переключатель командной строки Wno-unused-parameter.

Например:

gcc -Wno-unused-parameter test.c

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

Пол Хатчинсон
источник
7

Специфичный способ gcc / g ++ для подавления предупреждения о неиспользованном параметре для блока исходного кода - заключить его в следующие прагматические выражения:

#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

Маркировка атрибута является идеальным способом. Макро приводит к путанице. и используя 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».

ПРИМЕЧАНИЕ. Это просто для того, чтобы отключить предупреждение, а не для оптимизации.

user2452561
источник
1
Вы не добавляете какие-либо накладные расходы при обработке void(x), компилятор оптимизирует их.
Majora320
4

У меня та же проблема. Я использовал библиотеку третьей части. Когда я компилирую эту библиотеку, компилятор (gcc / clang) будет жаловаться на неиспользуемые переменные.

Как это

test.cpp: 29: 11: предупреждение: переменная 'magic' установлена, но не используется [-Wunused-but-set-variable] short magic [] = {

test.cpp: 84: 17: предупреждение: неиспользуемая переменная 'before_write' [-Wunused-variable] int64_t before_write = Thread :: currentTimeMillis ();

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

Таким образом, вам не нужно менять какой-либо код.

landerlyoung
источник
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
Это не очень хорошее соглашение, хотя компилятор почти наверняка оптимизирует его, не совсем понятно, что происходит, и может запутать статические проверки исходного кода. лучше воспользуйтесь одним из других предложений здесь ИМХО.
ideasman42
1
Я не могу поверить, что я все еще получаю ответы на это. В вопросе говорилось, что это для C. Да, на другом языке это не сработает.
Юстин
2
Я не использовал бы это, но +1 для фактора новизны.
мгалгс
2
проверка истинности переменных может давать предупреждения для структур. например. struct { int a; } b = {1}; if (b);GCC предупреждает used struct type value where scalar is required.
ideasman42
-1

Для справки, мне нравится ответ Джоба выше, но мне любопытно найти решение, использующее только имя переменной в выражении «ничего не делать»:

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

Конечно, у этого есть недостатки; например, без «неиспользованного» примечания это выглядит скорее как ошибка, а не как преднамеренная строка кода.

Преимущество в том, что DEFINE не требуется, и это избавляет от предупреждения.

Есть ли производительность, оптимизация или другие различия?

Доктор Персона Человек II
источник
2
Я либо использовал это с MSVC, но GCC выдает предупреждение «оператор без эффекта». Итак, решение Иова - путь.
Дмитрий Семикин
Этот подход все еще генерирует предупреждение в XCode
MOK9