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.