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


210

例如:

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

在C ++中,我能够对/*...*/参数进行注释。但是,当然不是在C中,它给了我错误error: parameter name omitted



4
@CiroSantilli这个问题有更多投票权,最好将另一个问题标记为重复。
sashoalm

1
另请参
见此

-Wno-unused-parameter,太吵了,很少会发现错误,尤其是。什么时候-Wshadow使用。
Trass3r

Answers:


297

我通常会这样写一个宏:

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

您可以将此宏用于所有未使用的参数。(请注意,这适用于任何编译器。)

例如:

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

45
我只是直接使用(void)x
Falken教授2012年

6
虽然这是AFAIK的唯一可移植方式,但是如果您以后使用该变量而忘记ro删除未使用的行,则可能会引起误解。这就是为什么GCC 不用的地方很好。
ideaman42

6
@CookSchelling:啊,但是你不应该那样使用它。做这样的事情:void f(int x) {UNUSED(x);}
2013年

9
@Alcott,因为(如我的情况)该函数可能是许多必须具有相同签名的函数之一,因为它们被函数指针引用。
josch 2014年

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))摆在争论前面。
josch 2014年

2
@josch我想你是完全正确的,但文档似乎暗示它应该放在的参数。这两个选项都可能受支持而没有问题。
Antonio

另请注意,这__attribute__((unused))专有的GCC扩展。其他一些编译器也支持它,但是我认为这不适用于MSVC。这不是直接编译标准虽然的一部分,所以这是不一样便携一些其他的选择
佐伊

58

您可以使用gcc / clang的未使用属性,但是我在标头中使用这些宏,以避免在整个源代码中__attribute__都有gcc特定的属性,而且到处都有点冗长/难看。

#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环境(__attribute__MSVC不支持AFAIK )?
富兰克林·于

那可以工作,但是dunder前缀的术语是为编译器保留的,因此我宁愿避免这种情况。
ideaman42

对于我的gcc而言,至少将属性说明符放在标识符似乎对功能,变量和参数正确的位置,因此,像#define POSSIBLY_UNUSED(identifier)attribute __((__ unused))标识符之类的东西可以用于所有三个
Britton Kerin

当我拿到它之后warning: unused parameter ‘foo’ [-Wunused-parameter](gcc 7.3.0)
ideaman42 '18

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语句将其括起来:

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


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);
}

现在,稍后将hash变量用于您的逻辑,但不需要bkt。将bkt定义为未使用,否则编译器会显示“未使用bkt设置bt”。

注意:这只是为了抑制警告而不是优化。


1
使用不会在处理中增加任何开销void(x),编译器会对其进行优化。
Majora320 '18

4

我遇到了同样的问题。我使用了第三方库。当我编译该库时,编译器(gcc / clang)将抱怨未使用的变量。

像这样

test.cpp:29:11:警告:已设置变量“魔术”,但未使用[-Wunused-but-set-variable]短魔术[] = {

test.cpp:84:17:警告:未使用的变量'before_write'[-Wunused-variable] 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
嗯 我不能说我喜欢这个,因为这假定所有涉及的参数都可以转换为布尔值。
Suma

1
即使编译器几乎肯定会对其进行优化,但这也不是一个很好的约定,它并不是很清楚发生了什么,并且可能使静态源检查器感到困惑。最好使用恕我直言的其他建议之一。
ideaman42

1
我不敢相信我仍然对此得到答复。问题表明这是给C的。是的,用另一种语言,这是行不通的。
Iustin 2013年

2
我不会使用它,但是+1是新奇因素。
mgalgs 2015年

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发出“声明无效”警告。因此,乔布斯的解决方案就是要走的路。
Dmitrii Semikin

这种方法仍然会产生Xcode的警告
MOK9
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.