¿Cómo suprimir las advertencias de "parámetro no utilizado" en C?

210

Por ejemplo:

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

En C ++ pude poner un /*...*/comentario sobre los parámetros. Pero no en C, por supuesto, donde me da el error error: parameter name omitted.

nixgadget
fuente
posible duplicado de ¿Qué es la mejor manera de suprimir "sin usar la variable x" claves -ADVERTENCIA
Ciro Santilli郝海东冠状病六四事件法轮功
44
@CiroSantilli Esta pregunta tiene más votos a favor, sería mejor marcar la otra pregunta como duplicada.
sashoalm
1
Vea también la versión C ++ de esta pregunta
Shafik Yaghmour,
-Wno-unused-parameter, es demasiado ruidoso y rara vez atrapa errores, especialmente. cuando -Wshadowse usa
Trass3r

Respuestas:

297

Normalmente escribo una macro como esta:

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

Puede usar esta macro para todos sus parámetros no utilizados. (Tenga en cuenta que esto funciona en cualquier compilador).

Por ejemplo:

void f(int x) {
    UNUSED(x);
    ...
}
Trabajo
fuente
45
Solo uso (vacío) x directamente
Prof. Falken
66
Si bien esta es la única forma portátil de AFAIK, la molestia con esto es que puede ser engañoso si usa la variable más adelante y olvida quitar la línea no utilizada. Es por eso que el GCC no utilizado es agradable.
ideasman42
66
@CookSchelling: Ah, pero no deberías usarlo así. Hacer algo como esto: void f(int x) {UNUSED(x);}.
Trabajo
9
@Alcott porque (como en mi caso) la función podría ser una de las muchas que tienen que tener la misma firma porque están referenciadas por un puntero de función.
josch
17
Estoy usando lo #define UNUSED(...) (void)(__VA_ARGS__)que me permite aplicar esto a múltiples variables.
Matthew Mitchell el
110

En gcc, puede etiquetar el parámetro con el unusedatributo .

Este atributo, asociado a una variable, significa que la variable está destinada a ser posiblemente no utilizada. GCC no generará una advertencia para esta variable.

En la práctica, esto se logra colocando __attribute__ ((unused))justo antes del parámetro. Por ejemplo:

void foo(workerid_t workerId) { }

se convierte

void foo(__attribute__((unused)) workerid_t workerId) { }
Flujo
fuente
24
Para cualquier novato como yo, esto significa poner __attribute__ ((unused))delante del argumento.
josch
2
@josch Creo que tiene toda la razón, pero la documentación parece implicar que debe colocarse después del parámetro. Ambas opciones son probablemente compatibles sin problemas.
Antonio
También tenga en cuenta que __attribute__((unused))es una extensión patentada de GCC . Es compatible con algunos otros compiladores, pero supongo que esto no funcionará con MSVC. Sin embargo, no es directamente parte del estándar del compilador, por lo que no es tan portátil como algunas otras opciones
Zoe el
58

Puede usar el atributo no utilizado de gcc / clang, sin embargo, uso estas macros en un encabezado para evitar tener atributos específicos de gcc en toda la fuente, también tener en __attribute__todas partes es un poco detallado / feo.

#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

Entonces puedes hacer ...

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

Prefiero esto porque obtienes un error si intentas usar bar el código en cualquier lugar para que no puedas dejar el atributo por error.

y para funciones ...

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

Nota 1):
Hasta donde yo sé, MSVC no tiene un equivalente a__attribute__((__unused__)) .

Nota 2):
la UNUSEDmacro no funcionará para los argumentos que contienen paréntesis,
por lo que si tiene un argumento float (*coords)[3] que no puede hacer,
float UNUSED((*coords)[3])o float (*UNUSED(coords))[3], este es el único inconveniente de la UNUSEDmacro que encontré hasta ahora, en estos casos retrocedo a(void)coords;

ideasman42
fuente
¿O tal vez solo #define __attribute__(x)para un entorno que no sea GCC (AFAIK, ninguno de ellos __attribute__es compatible con MSVC)?
Franklin Yu
Eso puede funcionar, pero los términos prefijados dunder están reservados para el compilador, así que prefiero evitar esto.
ideasman42
Para mi gcc, al menos poner el especificador de atributo antes del identificador parece funcionar correctamente para funcs, vars y parámetro, por lo que algo como #define POSSIBLY_UNUSED (identificador) atributo __ ((__ no utilizado )) identificador se puede utilizar para los tres
Britton Kerin
Cuando lo pongo después de obtener warning: unused parameter ‘foo’ [-Wunused-parameter](gcc 7.3.0)
ideasman42
19

Con gcc con el atributo no utilizado:

int foo (__attribute__((unused)) int bar) {
    return 0;
}
Osito de peluche
fuente
16

Al ver que esto está marcado como gcc, puede usar el interruptor de línea de comando Wno-unused-parameter.

Por ejemplo:

gcc -Wno-unused-parameter test.c

Por supuesto, esto afecta todo el archivo (y tal vez el proyecto depende de dónde configuró el interruptor), pero no tiene que cambiar ningún código.

Paul Hutchinson
fuente
7

Una forma específica de gcc / g ++ para suprimir la advertencia de parámetro no utilizado para un bloque de código fuente es encerrarlo con las siguientes declaraciones de pragma:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
<code with unused parameters here>
#pragma GCC diagnostic pop
Calma
fuente
Clang apoya estas pragmas diagnóstico, así clang.llvm.org/docs/...
eush77
4

Etiquetar el atributo es la forma ideal. MACRO conduce a la confusión en algún momento. y al usar void (x), estamos agregando una sobrecarga en el procesamiento.

Si no usa el argumento de entrada, use

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

Si no usa la variable definida dentro de la función

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

   api_call(x, hash, bkt);
}

Ahora más tarde usando la variable hash para su lógica, pero no necesita bkt. defina bkt como no utilizado, de lo contrario el compilador dice 'bkt set bt no utilizado ".

NOTA: Esto es solo para suprimir la advertencia, no para la optimización.

usuario2452561
fuente
1
No agrega ninguna sobrecarga en el procesamiento mediante el uso void(x), el compilador lo optimizará.
Majora320
4

Tengo el mismo problema. Usé una biblioteca de terceros. Cuando compilo esta biblioteca, el compilador (gcc / clang) se quejará de las variables no utilizadas.

Me gusta esto

test.cpp: 29: 11: advertencia: variable 'magia' establecida pero no utilizada [-Wunused-but-set-variable] magia corta [] = {

test.cpp: 84: 17: advertencia: variable no utilizada 'before_write' [-Wunused-variable] int64_t before_write = Thread :: currentTimeMillis ();

Entonces la solución es bastante clara. Agregar -Wno-unusedcomo gcc / clang CFLAG suprimirá todas las advertencias "no utilizadas", incluso aunque haya -Wallconfigurado.

De esta manera, NO NECESITA cambiar ningún código.

joven
fuente
1
Esto está bien si realmente quiere ignorar todas las advertencias no utilizadas, pero casi nunca es así. Por lo general, solo se deben ignorar las instancias específicas.
Dan Bechard el
1

En MSVC para suprimir una advertencia particular, es suficiente especificar el número para compilar como / wd #. Mi CMakeLists.txt contiene tal bloque:

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 ()

Ahora no puedo decir qué significa exactamente / wd4512 / wd4702 / wd4100 / wd4510 / wd4355 / wd4127, porque no presto ninguna atención al MSVC durante tres años, pero suprimen las advertencias superpedantes que no influyen en el resultado.

Bwana The Master
fuente
0

He visto que se usa este estilo:

if (when || who || format || data || len);
Iustin
fuente
14
Hm. No puedo decir que me guste, ya que esto supone que todos los parámetros involucrados se pueden convertir en bool.
Suma
1
Esto no es realmente una buena convención, aunque el compilador seguramente lo optimizará, no está realmente claro qué está pasando y podría confundir a los verificadores de fuente estática. mejor use una de las otras sugerencias aquí en mi humilde opinión.
ideasman42
1
No puedo creer que sigo recibiendo respuestas a esto. La pregunta decía que era para C. Sí, en otro idioma esto no funcionaría.
Iustin
2
No lo usaría pero +1 por el factor novedad.
mgalgs
2
verificar la verdad de las variables puede dar advertencias, para estructuras. p.ej. struct { int a; } b = {1}; if (b);GCC advierte used struct type value where scalar is required.
ideasman42
-1

Para el registro, me gusta la respuesta de Job anterior, pero tengo curiosidad acerca de una solución que solo usa el nombre de la variable en sí mismo en una declaración de "no hacer nada":

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

Claro, esto tiene inconvenientes; por ejemplo, sin la nota "no utilizada" parece un error en lugar de una línea de código intencional.

El beneficio es que no se necesita DEFINE y se elimina la advertencia.

¿Hay algún rendimiento, optimización u otras diferencias?

Dr. Persona Persona II
fuente
2
O bien usé esto con MSVC, pero GCC genera una advertencia de "declaración sin efecto". Entonces, la solución de Job es el camino a seguir.
Dmitrii Semikin
Este enfoque todavía genera una advertencia en XCode
MOK9