如何在C语言中禁止“未使用参数”的警告?

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

在C++中,我能够在参数周围放置一个/*...*/的注释。但是在C语言中不行,它会给我以下错误:

error: parameter name omitted


可能是如何抑制“未使用的变量x”警告的最佳方法的重复问题。 - Ciro Santilli OurBigBook.com
4
这个问题获得了更多的赞同票,最好将另一个问题标记为重复。 - sashoalm
1
请参考此问题的C++版本 - Shafik Yaghmour
-Wno-unused-parameter,它只是太嘈杂了,而且很少捕捉到错误,特别是在使用-Wshadow时。 - Trass3r
13个回答

390

我通常会编写这样的宏:

#define UNUSED(x) (void)(x)
你可以使用这个宏来处理所有未使用的参数。(注意,这适用于任何编译器。)
例如:
void f(int x) {
    UNUSED(x);
    ...
}

81
我只是直接使用(void)x。 - Prof. Falken
8
据我所知,尽管这是唯一可移植的方法,但其中的麻烦在于,如果您稍后使用变量并忘记删除未使用的行,则可能会导致误导。这就是为什么GCC的“__unused__”很好用的原因。 - ideasman42
13
@Alcott 因为(就像我这种情况)该函数可能是许多函数之一,它们必须具有相同的签名,因为它们被函数指针引用。 - josch
29
我正在使用 #define UNUSED(...) (void)(__VA_ARGS__),它允许我将其应用于多个变量。 - Matthew Mitchell
8
@pasignature:我建议让你的代码自解释。在我看来,UNUSED(argsv) 能够说明它的作用,而(void)argsv则不能。 - mtvec
显示剩余10条评论

150

在GCC中,你可以使用unused属性来标记参数。

该属性应用于变量上,表示该变量可能未被使用。GCC不会对此变量产生警告。

实际上,这是通过在参数前添加__attribute__((unused))来实现的。例如:

void foo(workerid_t workerId) { }

变成

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

27
对于像我这样的新手来说,这意味着在参数前面加上 __attribute__ ((unused)) - josch
2
@josch,我认为你是完全正确的,但文档似乎暗示应该将其放置在参数之后。这两个选项可能都没有问题支持。 - Antonio
2
请注意,__attribute__((unused))专有的GCC扩展。虽然一些其他编译器也支持它,但我认为这在MSVC上不起作用。它并不直接属于编译器标准,因此与其他选项相比,它的可移植性较差。 - Zoe stands with Ukraine
9
在GCC中称呼扩展程序为“专有”的说法,嗯,那个,这是某种说法。 - c-x-berger
作为一个小的概括,__attribute__ ((unused)) int myUnusedFunc() 不会产生未使用函数的警告。 - Alex Li
谢谢,伙计。添加dunder属性(Python风格)使其完美运行。 - undefined

73

你可以使用GCC或Clangunused属性。然而,我在头文件中使用这些宏,以避免在整个源代码中使用特定于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环境(据我所知,MSVC不支持任何__attribute__),只需使用#define __attribute__(x) - Franklin Yu
1
可以这样做,但是以双下划线开头的术语是为编译器保留的,所以我宁愿避免使用这种方式。 - ideasman42
对于我的gcc编译器,至少在函数、变量和参数上,在标识符之前放置属性说明符似乎是有效的,因此可以使用类似#define POSSIBLY_UNUSED(identifier) attribute((unused)) identifier的语句来处理所有三个。 - Britton Kerin
当我放置它后,我会得到 warning: unused parameter ‘foo’ [-Wunused-parameter](gcc 7.3.0)警告。 - ideasman42
UNREFERENCED_PARAMETER(p) 在 WinNT.h 中定义。 - david

33

看到这被标记为gcc,你可以使用命令行开关Wno-unused-parameter

例如:

gcc -Wno-unused-parameter test.c
当然,这会影响整个文件(根据您设置开关的位置,可能还包括整个项目),但您不需要更改任何代码。

如果你只想要单个参数而不是整个文件,那么这是不好的(即使你不想改变代码)。 - Fox
@Fox,这个信息已经包含在答案中了,为什么要重复呢? - LRDPRDX

24

使用带有GCC的unused属性:

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

14

在gcc/g++中抑制一个源代码块中未使用参数的警告的特定方法是将其用以下#pragma语句括起来:

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

1
Clang也支持这些诊断指示pragma https://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas - eush77

10
自从C++17起,可以使用[[maybe_unused]]属性来抑制有关未使用参数的警告。
根据OP的示例代码:
Bool NullFunc([[maybe_unused]] const struct timespec *when, [[maybe_unused]] const char *who)
{
   return TRUE;
}

1
请注意,该问题指定的是C语言而不是C ++。这个答案在C ++中可以正常工作。对于任何想尝试使用普通的C语言的人来说,它将会编译而没有警告(至少使用GCC),所以它“可以工作”,但是像clang-tidy这样的工具会讨厌它。 - chrBrd

7
我遇到了相同的问题。我使用了一个第三方库。当我编译这个库时,编译器(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();
因此解决方案非常明确。在gcc/clang CFLAG中添加-Wno-unused将抑制所有“unused”警告,即使您已经设置了-Wall。
这样,您无需更改任何代码。

2
这样做是可以忽略所有未使用的警告,但几乎从来不会这样。通常只有特定的情况需要忽略。 - Dan Bechard
你的问题与此不同。这个问题是关于“未使用的参数”警告,而你得到了“未使用的变量”警告。 - user7610

5
标记属性是理想的方式。使用宏有时会导致混淆。通过使用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但未使用”。
注意:这仅是为了抑制警告而不是优化。

2
使用void(x)不会增加任何处理开销,编译器会将其优化掉。 - Majora320

4

使用编译器特定的非标准机制告诉你的编译器

查看各个答案,了解__attribute__((unused))、各种#pragma等。可选地,为了可移植性,可以在其周围包装一个预处理器宏。

关闭警告

IDE可以通过视觉信号(不同颜色或下划线)来指示未使用的变量。在这种情况下,编译器警告可能是无用的。

在GCC和Clang中,在命令行末尾添加-Wno-unused-parameter选项(在打开未使用参数警告的所有选项之后,如-Wall、-Wextra)。

添加void转换

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

根据jamesdlin的回答Mailbag:关闭编译器警告

不要给变量命名(仅适用于C23和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引入了[[maybe_unused]]属性,已成为标准的一部分。在此之前,有[[gnu::unused]]。请参见clang文档的概述。(gnu::属性通常也可以在clang中使用。)

作为将C和C++特性更加接近的C标准化努力的一部分,在C23中我们获得了新的C语言属性。其中之一是[[maybe_unused]],它与C++版本的工作方式相同。在C23之前的版本中,[[gnu::unused]]编译器特定属性不可用,因为早期的C语言版本根本没有这些属性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接