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

Например:

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

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

13 ответов

Решение

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

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

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

Например:

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

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

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

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

void foo(workerid_t workerId) { }

становится

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

Вы можете использовать неиспользуемый атрибут 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;

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

Например:

gcc -Wno-unused-parameter test.c

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

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

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

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

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

Начиная с C++ 17, [[maybe_unused]] Атрибут может использоваться для подавления предупреждений о неиспользуемых параметрах.

На основе кода примера OP:

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

У меня та же проблема. Я использовал библиотеку третьей части. Когда я компилирую эту библиотеку, компилятор (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 задавать.

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

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

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

Сообщите своему компилятору, используя нестандартный механизм, специфичный для компилятора.

См. отдельные ответы на__attribute__((unused)), различный#pragmaс и так далее. При желании можно обернуть вокруг него макрос препроцессора для переносимости.

Выключить предупреждение

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

В GCC и Clang добавьте-Wno-unused-parameterопция в конце командной строки (после всех опций, которые включают предупреждение о неиспользуемых параметрах, например-Wall,-Wextra).

Добавить приведение к void

      void foo(int bar) {
    (void)bar;
}

Согласно ответу Джеймслина и Mailbag: закрытие предупреждений компилятора .

Не давайте переменной имя (только C23 и C++)

Не разрешено в C до стандарта C23, но с последним компилятором (в 2023 году) и в C++ (так как навсегда) можно это сделать

      void foo(int /*bar*/) {
    ...
}

См. документ N2480 «Разрешение безымянных параметров в предложении по определению функции (pdf)» и проверьте статус реализации по адресу https://en.cppreference.com/w/c/compiler_support .

GCC 11, Clang 11 и ICX 2022.2 (oneAPI 2022.3) поддерживают это.

Используйте стандартный атрибут (C23, C++17)

В C++17 естьатрибут, который стал частью стандарта. До этого было. Дополнительную информацию см. в документации clang . (gnu::атрибуты в целом работают и в clang.)

В рамках усилий по стандартизации C, сближающих функции C и C++, в C23 мы получаем новые атрибуты языка C.Один из них является[[maybe_unused]]который работает так же, как версия C++. [[gnu::unused]]Атрибут, специфичный для компилятора, недоступен в версиях до C23, поскольку более ранние версии языка C вообще не имели этих атрибутов.

В 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 в течение трех лет, но они подавляют суперпедантические предупреждения, которые не влияют на результат.

Я видел этот стиль используется:

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

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

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

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

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

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

Другие вопросы по тегам