web-dev-qa-db-fra.com

Pourquoi le compilateur ne m'a-t-il pas averti d'une instruction if vide?

J'utilise Keil uVision v4.74 et j'ai activé l'option "Tous les avertissements".

J'ai écrit le code intentionnel suivant:

if(condition matched)
{
 //do something
}

Lorsque j'ai reconstruit mon projet, j'ai reçu 0 erreurs, 0 avertissements.

Cependant, quand j'ai accidentellement écrit:

if(condition matched);
{
 //do something
}

J'ai également reçu 0 erreurs, 0 avertissements.

Il m'était presque impossible de découvrir qu'un petit ; suivant la condition if était à l'origine du problème.

Pourquoi le compilateur ne l'a-t-il pas traité comme un avertissement et m'a-t-il informé?

25

Ce n'est pas une erreur car une instruction vide c'est une instruction valide; cependant, comme il s'agit certainement d'un code suspect, c'est le candidat idéal pour un avertissement du compilateur - et en fait gcc -Wall -Wextra prévient:

int foo(int x) {
  if(x); {
    return 42;
  }
  return 64;
}

/tmp/gcc-Explorer-compiler116427-37-l1vpg4/example.cpp: In function 'int foo(int)':
2 : warning: suggest braces around empty body in an 'if' statement [-Wempty-body]
if(x); {
^

https://godbolt.org/g/RG1o7t

clang et VC++ le font aussi.

gcc 6 est encore plus intelligent (enfin, peut-être trop), et prend même l'indentation comme un indice que quelque chose ne va pas:

/tmp/gcc-Explorer-compiler116427-76-1sfy0y/example.cpp: In function 'int foo(int)':
2 : warning: suggest braces around empty body in an 'if' statement [-Wempty-body]
if(x); {
^
2 : warning: this 'if' clause does not guard... [-Wmisleading-indentation]
if(x); {
^~
2 : note: ...this statement, but the latter is misleadingly indented as if it is guarded by the 'if'
if(x); {
^

Donc, soit vous n'avez pas les avertissements suffisamment lancés, soit votre compilateur n'est pas assez intelligent.

Si vous n'avez pas la possibilité de passer à un compilateur plus utile, envisagez d'utiliser des outils d'analyse statique; par exemple, dans ce cas, cppcheck repère l'erreur (lorsque le --enable=all --inconclusive drapeaux):

[mitalia@mitalia ~/scratch]$ cppcheck --enable=all --inconclusive emptyif.c 
Checking emptyif.c...
[emptyif.c:2]: (warning, inconclusive) Suspicious use of ; at the end of 'if' statement.
[emptyif.c:1]: (style) The function 'foo' is never used.

Addendum - avertissements pertinents pour divers compilateurs (n'hésitez pas à mettre à jour)

pour récapituler, les options d'avertissement pertinentes sont les suivantes:

  • gcc -Wempty-body; inclus dans -Wextra;
  • gcc > = 6.0, également -Wmisleading-indentation peut aider; inclus dans -Wall;
  • clang -Wempty-body; inclus dans -Wextra aussi;
  • Visual C++ C439 , inclus dans /W3

Outils d'analyse statique:

  • cppcheck --enable=warning --inconclusive; inclus dans --enable=all --inconclusive
52
Matteo Italia

Comme l'indique la réponse de Matteo, le code est absolument valide. Il est interprété de cette façon:

if(condition)
    ;  // do nothing

// unrelated block
{
    // do something
}

C'est un peu une technicité, mais les conditions avec des corps vides ont des utilisations très agréables.

Lint et d'autres outils de contrôle d'intégrité du code vous avertiront du changement inattendu d'indentation et détecteront des erreurs supplémentaires qui peuvent être stylistiques mais pas techniquement des erreurs de compilation.

Ou des problèmes de sécurité, une altération variable, une gestion de la mémoire tampon, des problèmes de maintenance potentiels comme de mauvaises conversions, etc. Il y a énormément de problèmes de code qui ne tombent pas dans la catégorie des "erreurs de compilation".

Comme @ jpmc26 l'a mentionné, cette approche peut être meilleure car vous n'avez pas besoin de changer de compilateur pour l'utiliser. Bien que je trouve aussi personnellement la valeur de pouvoir exécuter les deux indépendamment.

2
davenpcj