Come eliminare gli avvisi di "parametro non utilizzato" in C?


210

Per esempio:

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

In C ++ sono stato in grado di inserire un /*...*/commento sui parametri. Ma non in C ovviamente, dove mi dà l'errore error: parameter name omitted.



4
@CiroSantilli Questa domanda ha più voti, sarebbe meglio contrassegnare l'altra domanda come duplicata.
sashoalm,


-Wno-unused-parameter, è troppo rumoroso e raramente cattura i bug esp. quando -Wshadowviene utilizzato.
Trass3r,

Risposte:


297

Di solito scrivo una macro come questa:

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

È possibile utilizzare questa macro per tutti i parametri non utilizzati. (Nota che funziona su qualsiasi compilatore.)

Per esempio:

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

45
Uso semplicemente (vuoto) x
Prof. Falken,

6
mentre questo è l'unico modo portatile AFAIK, il fastidio è che può essere fuorviante se si utilizza la variabile in un secondo momento e si dimentica ro rimuovere la linea non utilizzata. questo è il motivo per cui GCC non è utilizzato è carino.
ideasman42

6
@CookSchelling: Ah ma non dovresti usarlo così. Fare qualcosa del genere: void f(int x) {UNUSED(x);}.
Giobbe

9
@Alcott perché (come nel mio caso) la funzione potrebbe essere una delle tante che devono avere la stessa firma perché sono referenziate da un puntatore a funzione.
josch,

17
Sto usando ciò #define UNUSED(...) (void)(__VA_ARGS__)che mi permette di applicare questo a più variabili.
Matthew Mitchell,

110

In gcc, puoi etichettare il parametro con l' unusedattributo .

Questo attributo, associato a una variabile, significa che la variabile è probabilmente non utilizzata. GCC non produrrà un avviso per questa variabile.

In pratica ciò si ottiene inserendo __attribute__ ((unused))appena prima del parametro. Per esempio:

void foo(workerid_t workerId) { }

diventa

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

24
Per i neofiti come me, questo significa mettere __attribute__ ((unused))di fronte l'argomento.
josch,

2
@josch Penso che tu sia totalmente corretto, ma la documentazione sembra implicare che dovrebbe essere inserita dopo il parametro. Entrambe le opzioni sono probabilmente supportate senza problemi.
Antonio,

Si noti inoltre che __attribute__((unused))è un'estensione GCC proprietaria . È supportato da altri compilatori, ma suppongo che non funzionerà con MSVC. Tuttavia, non fa direttamente parte dello standard del compilatore, quindi non è portatile come alcune altre opzioni
Zoe,

58

Puoi usare l'attributo inutilizzato di gcc / clang, tuttavia io uso queste macro in un'intestazione per evitare di avere attributi specifici di gcc in tutta la fonte, anche se avere __attribute__ovunque è un po 'prolisso / brutto.

#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

Quindi puoi fare ...

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

Preferisco questo perché si ottiene un errore se si tenta di utilizzare bar il codice ovunque, quindi non è possibile lasciare l'attributo per errore.

e per le funzioni ...

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

Nota 1):
Per quanto ne so, MSVC non ha un equivalente di__attribute__((__unused__)) .

Nota 2):
la UNUSEDmacro non funzionerà per argomenti che contengono parentesi,
quindi se hai un argomento come float (*coords)[3] non puoi fare,
float UNUSED((*coords)[3])o float (*UNUSED(coords))[3], Questo è l'unico aspetto negativo della UNUSEDmacro che ho trovato finora, in questi casi ricado per(void)coords;


O forse solo #define __attribute__(x)per un ambiente non GCC (AFAIK nessuno dei quali __attribute__è supportato da MSVC)?
Franklin Yu,

Può funzionare, ma i termini con prefisso dunder sono riservati per il compilatore, quindi preferirei evitare questo.
ideasman42

Per il mio gcc almeno mettere l'identificatore di attributo prima che l'identificatore sembri funzionare correttamente per funcs, vars e parametro, quindi qualcosa come #define POSSIBLY_UNUSED (identificatore) attributo __ ((__ non utilizzato )) può essere usato per tutti e tre
Britton Kerin

Quando lo metto dopo che ottengo warning: unused parameter ‘foo’ [-Wunused-parameter](gcc 7.3.0)
ideasman42

19

Con gcc con l'attributo inutilizzato:

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

16

Vedendo che questo è contrassegnato come gcc è possibile utilizzare l'opzione della riga di comando Wno-unused-parameter .

Per esempio:

gcc -Wno-unused-parameter test.c

Naturalmente questo ha effetto sull'intero file (e forse sul progetto a seconda di dove si imposta l'interruttore) ma non è necessario modificare alcun codice.


7

Un modo specifico di gcc / g ++ per sopprimere l'avviso di parametro non utilizzato per un blocco di codice sorgente è racchiuderlo con le seguenti istruzioni pragma:

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

Clang supporta questi pragma diagnostici nonché clang.llvm.org/docs/...
eush77

4

L'etichettatura dell'attributo è il modo ideale. MACRO porta a un po 'di confusione. e usando void (x), stiamo aggiungendo un overhead nell'elaborazione.

Se non si utilizza l'argomento input, utilizzare

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

Se non si utilizza la variabile definita all'interno della funzione

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

   api_call(x, hash, bkt);
}

Ora più tardi usa la variabile hash per la tua logica ma non ha bisogno di bkt. definire bkt come inutilizzato, altrimenti il ​​compilatore dice "set bt non utilizzato".

NOTA: Questo è solo per sopprimere l'avvertimento non per l'ottimizzazione.


1
Non si aggiunge alcun sovraccarico nell'elaborazione utilizzando void(x), il compilatore lo ottimizzerà.
Majora320,

4

Ho avuto lo stesso problema. Ho usato una libreria di terze parti. Quando compilo questa libreria, il compilatore (gcc / clang) si lamenterà delle variabili non utilizzate.

Come questo

test.cpp: 29: 11: avviso: variabile 'magic' impostata ma non utilizzata [-Wunused-but-set-variabile] short magic [] = {

test.cpp: 84: 17: avviso: variabile inutilizzata 'before_write' [-Wunused-variabile] int64_t before_write = Thread :: currentTimeMillis ();

Quindi la soluzione è abbastanza chiara. L'aggiunta -Wno-unusedcome CFLAG gcc / clang eliminerà tutti gli avvisi "non utilizzati", anche se si è pensato di aver -Wallimpostato.

In questo modo, NON È NECESSARIO modificare alcun codice.


1
Questo va bene se in realtà vuoi ignorare tutti gli avvisi inutilizzati, ma non è quasi mai il caso. Di solito sono solo istanze specifiche che vuoi ignorare.
Dan Bechard,

1

In MSVC per sopprimere un particolare avviso è sufficiente specificare il suo numero da compilare come / wd #. My CMakeLists.txt contiene tale blocco:

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

Ora non posso dire cosa significhi esattamente / wd4512 / wd4702 / wd4100 / wd4510 / wd4355 / wd4127, perché non prendo attenzione a MSVC per tre anni, ma sopprimono gli avvisi superpedantici che non influenzano il risultato.


0

Ho visto usare questo stile:

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

14
Hm. Non posso dire che mi piace, dato che presuppone che tutti i parametri coinvolti possano essere convertiti in bool.
Suma,

1
Questa non è davvero una buona convenzione, anche se il compilatore quasi sicuramente lo ottimizzerà, non è davvero chiaro cosa stia succedendo e potrebbe confondere i controlli statici della fonte. meglio usare uno degli altri suggerimenti qui IMHO.
ideasman42

1
Non riesco a credere di ricevere ancora risposte a questo. La domanda affermava che era per C. Sì, in un'altra lingua non avrebbe funzionato.
Iustin,

2
Non lo userei ma +1 per il fattore novità.
mgalgs

2
verificare la verità delle variabili può dare avvertimenti, per le strutture. per esempio. struct { int a; } b = {1}; if (b);GCC avverte, used struct type value where scalar is required.
ideasman42

-1

Per la cronaca, mi piace la risposta di Job sopra, ma sono curioso di una soluzione che utilizza il nome della variabile da solo in un'istruzione "do-nothing":

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

Certo, questo ha degli svantaggi; per esempio, senza la nota "non utilizzata" sembra un errore piuttosto che una riga di codice intenzionale.

Il vantaggio è che non è necessario DEFINE e si elimina l'avvertimento.

Ci sono prestazioni, ottimizzazione o altre differenze?


2
O l'ho usato con MSVC, ma GCC genera un avviso "istruzione senza effetto". Quindi, la soluzione di Job è la strada da percorrere.
Dmitrii Semikin

Questo approccio genera ancora un avviso in XCode
MOK9
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.