web-dev-qa-db-fra.com

Comment est-il préférable de faire taire un avertissement concernant les variables non utilisées?

J'ai une application multiplate-forme et dans certaines de mes fonctions, toutes les valeurs transmises aux fonctions ne sont pas utilisées. Par conséquent, GCC m'avertit qu'il existe des variables non utilisées.

Quel serait le meilleur moyen de coder l’avertissement?

Un #ifdef autour de la fonction? 

#ifdef _MSC_VER
void ProcessOps::sendToExternalApp(QString sAppName, QString sImagePath, qreal qrLeft, qreal qrTop, qreal qrWidth, qreal qrHeight)
#else
void ProcessOps::sendToExternalApp(QString sAppName, QString sImagePath, qreal /*qrLeft*/, qreal /*qrTop*/, qreal /*qrWidth*/, qreal /*qrHeight*/)
#endif
{

C’est tellement moche mais cela semble être la préférence du compilateur.

Ou dois-je attribuer zéro à la variable à la fin de la fonction? (ce que je déteste parce que cela modifie quelque chose dans le déroulement du programme pour faire taire un avertissement du compilateur).

Y a-t-il un moyen correct?

185
Phil Hannent

Vous pouvez le mettre dans l'expression "(void)var;" (ne fait rien) afin qu'un compilateur le voit utilisé. Ceci est portable entre les compilateurs.

Par exemple.

void foo(int param1, int param2)
{
    (void)param2;
    bar(param1);
}

Ou,

#define UNUSED(expr) do { (void)(expr); } while (0)
...

void foo(int param1, int param2)
{
    UNUSED(param2);
    bar(param1);
}
270
Alex B

Dans GCC et Clang, vous pouvez utiliser la directive de pré-processeur __attribute__((unused)) pour atteindre votre objectif.
Par exemple:

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

Votre solution actuelle est préférable: commentez le nom du paramètre si vous ne l'utilisez pas. Cela s'applique à tous les compilateurs, vous n'avez donc pas besoin d'utiliser le pré-processeur pour le faire spécialement pour GCC.

34
alex tingle

C++ 17 fournit maintenant l'attribut [[maybe_unused]].

http://fr.cppreference.com/w/cpp/language/attributes

Assez gentil et standard.

29
scx

Un collègue vient de m'indiquer cette jolie petite macro ici

Pour plus de facilité, je vais inclure la macro ci-dessous.

#ifdef UNUSED
#Elif defined(__GNUC__) 
# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) 
#Elif defined(__LCLINT__) 
# define UNUSED(x) /*@unused@*/ x 
#else 
# define UNUSED(x) x 
#endif

void dcc_mon_siginfo_handler(int UNUSED(whatsig))
23
user194119

gcc ne marque pas ces avertissements par défaut. Cet avertissement doit avoir été activé soit explicitement en passant -Wunused-parameter au compilateur, soit implicitement en passant -Wall -Wextra (ou éventuellement une autre combinaison d'indicateurs).

Les avertissements de paramètres non utilisés peuvent simplement être supprimés en passant -Wno-unused-parameter au compilateur, mais notez que cet indicateur de désactivation doit apparaître après tous les indicateurs d'activation possibles pour cet avertissement dans la ligne de commande du compilateur afin qu'il puisse prendre effet.

22
Digital Trauma

Une méthode encore plus simple consiste à commenter les noms de variables:

int main(int /* argc */, char const** /* argv */) {
  return 0;
}
21
Marcin Wyszynski

Mise à jour C++ 17

En C++ 17, nous obtenons l'attribut [[peut-être_utilisé]] qui est couvert dans [dcl.attr.unused]

L'attribut-jeton Maybe_unused indique qu'un nom ou une entité est peut-être intentionnellement inutilisé. Cela devrait apparaissent au plus une fois dans chaque liste d'attributs et aucune clause attribut-argument ne doit être présente . ...

Exemple:

 [[maybe_unused]] void f([[maybe_unused]] bool thing1,
                        [[maybe_unused]] bool thing2) {
  [[maybe_unused]] bool b = thing1 && thing2;
    assert(b);
 }

Les implémentations ne doivent pas avertir que b est inutilisé, que NDEBUG soit défini ou non. —Fin exemple]

Pour l'exemple suivant:

int foo ( int bar) {
    bool unused_bool ;
    return 0;
}

Clang et gcc génèrent tous deux un diagnostic utilisant -Wall -Wextra pour bar et Unnamed_bool ( Voir en direct ).

Lors de l'ajout de [[peut-être_utilisé]], les diagnostics sont réduits au silence:

int foo ([[maybe_unused]] int bar) {
    [[maybe_unused]] bool unused_bool ;
    return 0;
}

le voir en direct .

Avant C++ 17

En C++ 11, une variante de la macro UNUSED pourrait être formée à l'aide d'une expression lambda (via Ben Deane) avec une capture de la variable non utilisée:

#define UNUSED(x) [&x]{}()

L'invocation immédiate de l'expression lambda doit être optimisée, à l'aide de l'exemple suivant:

int foo (int bar) {
    UNUSED(bar) ;
    return 0;
}

on peut voir dans godbolt que l'appel est optimisé:

foo(int):
xorl    %eax, %eax
ret
16
Shafik Yaghmour

manière sans macro et portable de déclarer un ou plusieurs paramètres non utilisés:

template <typename... Args> inline void unused(Args&&...) {}

int main(int argc, char* argv[])
{
    unused(argc, argv);
    return 0;
}
11
Philippe

L'utilisation de directives de pré-traitement est considérée comme un mal la plupart du temps. Idéalement, vous voulez les éviter comme le ravageur. N'oubliez pas qu'il est facile de faire comprendre votre code au compilateur, ce qui est beaucoup plus difficile pour les autres programmeurs. Quelques dizaines de cas comme celui-ci ici et là rendent très difficile la lecture pour vous-même ou pour les autres actuellement.

Une solution consiste peut-être à regrouper vos paramètres dans une sorte de classe d'arguments. Vous pouvez alors utiliser uniquement un sous-ensemble de variables (équivalent à l'attribution réelle de 0) ou avoir différentes spécialisations de cette classe d'arguments pour chaque plate-forme. Cela ne vaut peut-être pas la peine, vous devez analyser si cela convient.

Si vous parvenez à lire des modèles impossibles, vous pourrez trouver des astuces avancées dans le livre "C++ exceptionnel". Si les personnes qui liraient votre code pourraient obtenir que leurs compétences englobent les trucs fous enseignés dans ce livre, alors vous aurez un beau code qui peut également être lu facilement. Le compilateur sera également bien conscient de ce que vous faites (au lieu de tout cacher en prétraitant)

7
Ben Dadsetan

Tout d'abord, l'avertissement est généré par la définition de variable dans le fichier source et non dans le fichier d'en-tête. L'en-tête peut rester vierge et devrait, puisque vous pouvez utiliser quelque chose comme doxygen pour générer la documentation de l'API. 

Je vais supposer que vous avez une implémentation complètement différente dans les fichiers source. Dans ces cas, vous pouvez commenter le paramètre incriminé ou simplement l'écrire. 

Exemple:

func(int a, int b)
{
    b;
    foo(a);
}

Cela peut sembler cryptique, alors définissez une macro comme UNUSED. Voici comment MFC l'a fait:

#ifdef _DEBUG
#define UNUSED(x)
#else
#define UNUSED(x) x
#endif

Comme cela, vous voyez que l'avertissement est toujours dans les versions de débogage, cela pourrait être utile.

6
rioki

N'est-il pas prudent de toujours commenter les noms de paramètres? Si ce n'est pas vous pouvez faire quelque chose comme

#ifdef _MSC_VER
# define P_(n) n
#else
# define P_(n)
#endif

void ProcessOps::sendToExternalApp(
    QString sAppName, QString sImagePath,
    qreal P_(qrLeft), qreal P_(qrTop), qreal P_(qrWidth), qreal P_(qrHeight))

C'est un peu moins moche.

4

Vous pouvez utiliser __unused pour indiquer au compilateur que la variable peut ne pas être utilisée.

- (void)myMethod:(__unused NSObject *)theObject    
{
    // there will be no warning about `theObject`, because you wrote `__unused`

    __unused int theInt = 0;
    // there will be no warning, but you are still able to use `theInt` in the future
}
2
OlDor

Utilisez l'indicateur du compilateur, par exemple drapeau pour GCC: -Wno-unused-variable

2
user6468372

L'utilisation d'une UNREFERENCED_PARAMETER(p) pourrait fonctionner. Je sais qu'il est défini dans WinNT.h pour les systèmes Windows et peut également être défini pour gcc également (s'il ne l'a pas déjà).

UNREFERENCED PARAMETER(p) est défini comme

#define UNREFERENCED_PARAMETER(P)          (P)

dans WinNT.h.

2
Joshua

En C++ 11, voici la solution que j'utilise:

template<typename... Ts> inline void Unreferenced(Ts&&...) {}

int Foo(int bar) 
{
    Unreferenced(bar);
    return 0;
}

int Foo2(int bar1, int bar2) 
{
    Unreferenced(bar1, bar2);
    return 0;
}

Vérifié pour être portable (au moins sur les msvc, clang et gcc modernes) et ne génère pas de code supplémentaire lorsque les optimisations sont activées . En l'absence d'optimisation, l'appel de fonction supplémentaire est exécuté et les références aux paramètres sont copiées dans la pile. il n'y a pas de macros impliquées.

Si le code supplémentaire est un problème, vous pouvez utiliser cette déclaration à la place:

(decltype(Unreferenced(bar1, bar2)))0;

mais à ce stade, une macro offre une meilleure lisibilité:

#define UNREFERENCED(...) { (decltype(Unreferenced(__VA_ARGS__)))0; }
1
Nampo

Cela fonctionne bien mais nécessite C++ 11

template <typename ...Args>
void unused(Args&& ...args)
{
  (void)(sizeof...(args));
}
1

J'ai trouvé que la plupart des réponses présentées ne fonctionnaient que pour les variables locales inutilisées et provoqueraient une erreur de compilation pour les variables globales statiques inutilisées. 

Une autre macro devait supprimer l’avertissement de la variable globale statique non utilisée.

template <typename T>
const T* UNUSED_VARIABLE(const T& dummy) { 
    return &dummy;
}
#define UNUSED_GLOBAL_VARIABLE(x) namespace {\
    const auto dummy = UNUSED_VARIABLE(x);\
}

static int a = 0;
UNUSED_GLOBAL_VARIABLE(a);

int main ()
{
    int b = 3;
    UNUSED_VARIABLE(b);
    return 0;
}

Cela fonctionne car aucun avertissement ne sera signalé pour une variable globale non statique dans un espace de noms anonyme. 

C++ 11 est requis cependant

 g++  -Wall -O3  -std=c++11 test.cpp
0
FaceBro