web-dev-qa-db-fra.com

Qu'est-ce que le casting de `void` fait vraiment?

Une instruction souvent utilisée telle que (void)x; permet de supprimer les avertissements concernant la variable inutilisée x. Mais si j'essaie de compiler ce qui suit, j'obtiens des résultats que je ne comprends pas très bien:

int main()
{
    int x;
    (short)x;
    (void)x;
    (int)x;
}

En compilant ceci avec g ++, je reçois les avertissements suivants:

$ g++ test.cpp -Wall -Wextra -o test
test.cpp: In function ‘int main()’:
test.cpp:4:13: warning: statement has no effect [-Wunused-value]
     (short)x;
             ^
test.cpp:6:11: warning: statement has no effect [-Wunused-value]
     (int)x;
           ^

Je conclus donc que la conversion dans void est très différente de la conversion dans un autre type, que le type de cible soit identique à decltype(x) ou différent. Je suppose que les explications possibles sont les suivantes:

  • C’est simplement une convention selon laquelle (void)x;, mais pas les autres distributions, supprime les avertissements. Toutes les déclarations n'ont également aucun effet.
  • Cette différence est liée au fait que void x; n'est pas une instruction valide, alors que short x; l'est.

Laquelle de ces éventuelles est la plus correcte? Sinon, comment expliquer la différence entre les avertissements du compilateur?

27
Ruslan

Casting to void est utilisé pour supprimer les avertissements du compilateur. Le Standard dit au §5.2.9/4,

Toute expression peut être explicitement convertie en type "cv void". Le La valeur d'expression est ignorée.

30
Rahul Tripathi

Cette déclaration:

(void)x;

Dit "Ignorer la valeur de x." void n'existe pas - c'est l'absence d'un type. Donc, c'est très différent de ça:

(int)x;

Ce qui dit "Traite x comme s'il s'agissait d'un entier." Lorsque l'entier résultant est ignoré, vous recevez un avertissement (s'il est activé).

Lorsque vous ignorez quelque chose qui n’est rien, cela n’est pas considéré comme un problème par GCC - et ce pour une bonne raison, puisque le fait de passer à vide est un moyen idiomatique d’ignorer une variable explicitement en C et C++.

10
John Zwinck

La norme n'exige pas de générer un avertissement ("diagnostic" en standard) pour les variables locales non utilisées ou les paramètres de fonction. De même, il ne précise pas comment un tel avertissement pourrait être supprimé. Convertir une expression de variable en void pour supprimer cet avertissement est devenu un idiome dans les communautés C++ et C++, car le résultat ne peut pas être utilisé de quelque manière que ce soit (autre que (int)x), il est donc peu probable que le code correspondant soit simplement manquant. Par exemple.:

(int)x;  // maybe you meant f((int)x);
(void)x; // cannot have intended f((void)x);
(void)x; // but remote possibility: f((void*)x);

Personnellement, je trouve cette convention encore trop obscure, c'est pourquoi je préfère utiliser un modèle de fonction:

template<typename T>
inline void ignore(const T&) {} // e.g. ignore(x);

La façon idiomatique d'ignorer les paramètres de fonction consiste toutefois à omettre leur nom (comme indiqué ci-dessus). Une utilisation fréquente de cette fonction est lorsque je dois pouvoir nommer un paramètre de fonction dans un code compilé conditionnellement tel que assert. Je trouve par exemple Les éléments suivants sont plus lisibles que l'utilisation de #ifdef NDEBUG:

void rate(bool fantastic)
{
    assert(fantastic);
    ignore(fantastic);
}
4
Arne Vogel

Utilisation possible:

auto it = list_.before_begin();
for (auto& entry : list_)
{
    (void)entry; //suppress warning
    ++it;
}

Maintenant, l'itérateur 'it' pointe vers le dernier élément

0
Traummaennlein