Comment supprimer les avertissements de «paramètre inutilisé» en C?


210

Par exemple:

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

En C ++, j'ai pu mettre un /*...*/commentaire sur les paramètres. Mais pas en C bien sûr, où ça me donne l'erreur error: parameter name omitted.



4
@CiroSantilli Cette question a plus de votes positifs, il serait préférable de marquer l'autre question comme doublon.
sashoalm


-Wno-unused-parameter, c'est juste trop bruyant et attrape rarement des bugs en particulier. quand -Wshadowest utilisé.
Trass3r

Réponses:


297

J'écris généralement une macro comme celle-ci:

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

Vous pouvez utiliser cette macro pour tous vos paramètres inutilisés. (Notez que cela fonctionne sur n'importe quel compilateur.)

Par exemple:

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

45
J'utilise juste (void) x directement
Prof. Falken

6
Bien que ce soit le seul moyen portable AFAIK, le désagrément avec cela est qu'il peut être trompeur si vous utilisez la variable plus tard et oubliez de supprimer la ligne inutilisée. c'est pourquoi GCC inutilisé est agréable.
ideasman42

6
@CookSchelling: Ah mais vous ne devriez pas l'utiliser comme ça. Faites quelque chose comme ceci: void f(int x) {UNUSED(x);}.
Job

9
@Alcott car (comme dans mon cas) la fonction peut être l'une des nombreuses qui doivent avoir la même signature car elles sont référencées par un pointeur de fonction.
josch

17
J'utilise #define UNUSED(...) (void)(__VA_ARGS__)ce qui me permet d'appliquer cela à plusieurs variables.
Matthew Mitchell

110

Dans gcc, vous pouvez étiqueter le paramètre avec l' unusedattribut .

Cet attribut, attaché à une variable, signifie que la variable est censée être éventuellement inutilisée. GCC ne produira pas d'avertissement pour cette variable.

En pratique, cela se fait en mettant __attribute__ ((unused))juste avant le paramètre. Par exemple:

void foo(workerid_t workerId) { }

devient

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

24
Pour tous les débutants comme moi, cela signifie mettre __attribute__ ((unused))en avant l'argument.
josch

2
@josch Je pense que vous avez tout à fait raison, mais la documentation semble impliquer qu'elle devrait être placée après le paramètre. Les deux options sont probablement prises en charge sans problème.
Antonio

Notez également qu'il __attribute__((unused))s'agit d' une extension GCC propriétaire . Il est pris en charge par d'autres compilateurs, mais je suppose que cela ne fonctionnera pas avec MSVC. Ce n'est pas directement une partie de la norme du compilateur, donc ce n'est pas aussi portable que d'autres options
Zoe

58

Vous pouvez utiliser l'attribut inutilisé de gcc / clang, mais j'utilise ces macros dans un en-tête pour éviter d'avoir des attributs spécifiques à gcc partout dans la source, avoir aussi __attribute__partout est un peu bavard / laid.

#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

Ensuite, vous pouvez faire ...

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

Je préfère cela parce que vous obtenez une erreur si vous essayez d'utiliser barle code n'importe où, vous ne pouvez donc pas laisser l'attribut par erreur.

et pour les fonctions ...

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

Note 1):
Pour autant que je sache, MSVC n'a pas d'équivalent à __attribute__((__unused__)).

Note 2):
La UNUSEDmacro ne fonctionnera pas pour les arguments qui contiennent des parenthèses,
donc si vous avez un argument comme float (*coords)[3] vous ne pouvez pas le faire,
float UNUSED((*coords)[3])ou float (*UNUSED(coords))[3], c'est le seul inconvénient de la UNUSEDmacro que j'ai trouvé jusqu'à présent, dans ces cas, je retombe à(void)coords;


Ou peut-être juste #define __attribute__(x)pour un environnement non-GCC (aucun AFAIK n'est __attribute__pris en charge par MSVC)?
Franklin Yu

Cela peut fonctionner, mais les termes préfixés dunder sont réservés au compilateur, je préfère donc éviter cela.
ideasman42

Pour mon gcc, au moins mettre le spécificateur d'attribut avant que l'identifiant semble fonctionner correctement pour les fonctions, les vars et les paramètres, donc quelque chose comme #define POSSIBLY_UNUSED (identifier) ​​l' attribut __ ((__ non utilisé )) identifiant peut être utilisé pour les trois
Britton Kerin

Quand je le mets après avoir reçu warning: unused parameter ‘foo’ [-Wunused-parameter](gcc 7.3.0)
ideasman42

19

Avec gcc avec l'attribut inutilisé:

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

16

Voyant que cela est marqué comme gcc, vous pouvez utiliser le commutateur de ligne de commande Wno-unused-parameter.

Par exemple:

gcc -Wno-unused-parameter test.c

Bien sûr, cela affecte l'ensemble du fichier (et peut-être le projet en fonction de l'endroit où vous définissez le commutateur), mais vous n'avez pas à modifier de code.


7

Une manière spécifique à gcc / g ++ de supprimer l'avertissement de paramètre inutilisé pour un bloc de code source consiste à le joindre aux instructions pragma suivantes:

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

Clang soutient ces pragmas de diagnostic et clang.llvm.org/docs/...
eush77

4

L'étiquetage de l'attribut est le moyen idéal. MACRO conduit parfois à la confusion. et en utilisant void (x), nous ajoutons une surcharge dans le traitement.

Si vous n'utilisez pas d'argument d'entrée, utilisez

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

Si vous n'utilisez pas la variable définie à l'intérieur de la fonction

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

   api_call(x, hash, bkt);
}

Maintenant, utilisez plus tard la variable de hachage pour votre logique, mais n'a pas besoin de bkt. définir bkt comme inutilisé, sinon le compilateur dit "bkt set bt not used".

REMARQUE: il s'agit simplement de supprimer l'avertissement et non d'optimiser.


1
Vous n'ajoutez aucune surcharge dans le traitement en utilisant void(x), le compilateur l'optimisera.
Majora320

4

J'ai le même problème. J'ai utilisé une bibliothèque tierce. Lorsque je compile cette bibliothèque, le compilateur (gcc / clang) se plaindra des variables inutilisées.

Comme ça

test.cpp: 29: 11: avertissement: variable 'magic' définie mais non utilisée [-Wunused-but-set-variable] short magic [] = {

test.cpp: 84: 17: avertissement: variable inutilisée 'before_write' [-Wunused-variable] int64_t before_write = Thread :: currentTimeMillis ();

La solution est donc assez claire. L'ajout en -Wno-unusedtant que gcc / clang CFLAG supprimera tous les avertissements "inutilisés", même si vous les avez -Walldéfinis.

De cette façon, vous N'AVEZ PAS BESOIN de modifier un code.


1
C'est très bien si vous voulez réellement ignorer tous les avertissements inutilisés, mais ce n'est presque jamais le cas. Ce sont généralement des instances spécifiques que vous souhaitez ignorer.
Dan Bechard

1

Dans MSVC pour supprimer un avertissement particulier, il suffit de spécifier le numéro à compiler sous / wd #. Mon CMakeLists.txt contient tel le bloc:

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

Maintenant, je ne peux pas dire ce que signifie exactement / wd4512 / wd4702 / wd4100 / wd4510 / wd4355 / wd4127, car je ne prête aucune attention à MSVC pendant trois ans, mais ils suppriment les avertissements superpédantaires qui n'influencent pas le résultat.


0

J'ai vu ce style utilisé:

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

14
Hm. Je ne peux pas dire que j'aime cela, car cela suppose que tous les paramètres impliqués peuvent être convertis en booléens.
Suma

1
Ce n'est pas vraiment une bonne convention, même si le compilateur l'optimisera certainement, ce qui ne se passe pas vraiment et pourrait confondre les vérificateurs de sources statiques. mieux utiliser l'une des autres suggestions ici à mon humble avis.
ideasman42

1
Je ne peux pas croire que je reçois toujours des réponses à cela. La question indiquait que c'était pour C. Oui, dans une autre langue, cela ne fonctionnerait pas.
Iustin

2
Je ne l'utiliserais pas mais +1 pour le facteur nouveauté.
mgalgs

2
vérifier la vérité des variables peut donner des avertissements, pour les structures. par exemple. struct { int a; } b = {1}; if (b);GCC met en garde, used struct type value where scalar is required.
ideasman42

-1

Pour mémoire, j'aime la réponse de Job ci-dessus, mais je suis curieux de voir une solution utilisant simplement le nom de variable par lui-même dans une instruction "ne rien faire":

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

Bien sûr, cela a des inconvénients; par exemple, sans la note "inutilisée", cela ressemble à une erreur plutôt qu'à une ligne de code intentionnelle.

L'avantage est qu'aucun DEFINE n'est nécessaire et il supprime l'avertissement.

Existe-t-il des différences de performances, d'optimisation ou autres?


2
J'ai utilisé ceci avec MSVC, mais GCC lève l'avertissement "déclaration sans effet". La solution de Job est donc la voie à suivre.
Dmitrii Semikin

Cette approche génère toujours un avertissement dans XCode
MOK9
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.