Que fait exactement un bloc #if 0… #endif?

124

En C / C ++

Qu'arrive-t-il au code placé entre un bloc #if 0/ #endif?

#if 0

//Code goes here

#endif

Le code est-il simplement ignoré et n'est donc pas exécuté?

vette982
la source
17
Il s'agit d'une technique utilisée pour commenter de grandes quantités de code ou pour permettre de tester l'inclusion de blocs de code. Sans cette fonctionnalité, il faudrait soit préfixer chaque ligne avec, //soit commencer la section avec /*et terminer la section avec */. Le problème avec ces dernières techniques est que les commentaires ne sont pas imbriqués, le développeur doit donc vérifier et gérer tout */entre le début et la fin.
Thomas Matthews

Réponses:

141

Non seulement il n'est pas exécuté, mais il n'est même pas compilé.

#ifest une commande de préprocesseur, qui est évaluée avant l'étape de compilation proprement dite. Le code à l'intérieur de ce bloc n'apparaît pas dans le binaire compilé.

Il est souvent utilisé pour supprimer temporairement des segments de code dans le but de les réactiver plus tard.

David
la source
1
Cela est vrai de tout type de commentaire. La différence importante est la nidification.
Samy Bencherif le
73

C'est identique à commenter le bloc, sauf avec une différence importante: l'imbrication n'est pas un problème. Considérez ce code:

foo();
bar(x, y); /* x must not be NULL */
baz();

Si je veux le commenter, je pourrais essayer:

/*
foo();
bar(x, y); /* x must not be NULL */
baz();
*/

Bzzt. Erreur de syntaxe! Pourquoi? Parce que les commentaires de bloc ne sont pas imbriqués, et ainsi (comme vous pouvez le voir à partir de la coloration syntaxique de SO), */après le mot «NULL» termine le commentaire, rendant l' bazappel non commenté et */après bazune erreur de syntaxe. D'autre part:

#if 0
foo();
bar(x, y); /* x must not be NULL */
baz();
#endif

Fonctionne pour commenter le tout. Et les #if 0s vont s'emboîter, comme ceci:

#if 0
pre_foo();
#if 0
foo();
bar(x, y); /* x must not be NULL */
baz();
#endif
quux();
#endif

Bien sûr, cela peut devenir un peu déroutant et devenir un casse-tête de maintenance s'il n'est pas commenté correctement.

Tyler McHenry
la source
5
Notez simplement que le code à l'intérieur de #if doit être lexicalement correct (par opposition aux commentaires) et que les directives du préprocesseur sont toujours en vigueur (idem).
jpalecek
@David: Ce n'est pas lexicalement correct, mais il compilera quand même. Le code n'a donc pas besoin d'être lexiquement correct.
Dennis Zickefoose
1
@Dennis, je reçois foo.c:3: unterminated string or character constantde gcc, qu'est-ce que vous utilisez?
David X
18

Il commente en permanence ce code afin que le compilateur ne le compilera jamais.

Le codeur peut plus tard modifier le #ifdef pour que ce code soit compilé dans le programme s'il le souhaite.

C'est exactement comme si le code n'existe pas.

Nilbert
la source
15

Que fait exactement un bloc #if 0… #endif?

Cela vous indique que l'auteur n'a évidemment jamais entendu parler d'un système de contrôle de version. Ce qui, à son tour, vous dit de courir le plus loin possible ...

Jörg W Mittag
la source
12

Je voudrais ajouter pour le #elsecas:

#if 0
   /* Code here will NOT be complied. */
#else
   /* Code will be compiled. */
#endif


#if 1
   /* Code will be complied. */
#else
   /* Code will NOT be compiled. */
#endif
Steven Xu
la source
7

Lorsque le préprocesseur voit #if, il vérifie si le jeton suivant a une valeur différente de zéro. Si c'est le cas, il conserve le code pour le compilateur. Si ce n'est pas le cas, il se débarrasse de ce code afin que le compilateur ne le voit jamais.

Si quelqu'un dit #if 0, il commente effectivement le code pour qu'il ne soit jamais compilé. Vous pouvez penser à cela de la même manière que s'ils avaient mis / * ... * / autour de lui. Ce n'est pas tout à fait la même chose, mais cela a le même effet.

Si vous voulez comprendre ce qui s'est passé en détail, vous pouvez souvent regarder. De nombreux compilateurs vous permettront de voir les fichiers une fois le préprocesseur exécuté. Par exemple, sur Visual C ++, la commande switch / P exécutera le préprocesseur et placera les résultats dans un fichier .i.

Steve Rowe
la source
Pas assez. Le préprocesseur analyse par ligne plutôt que par jeton. Selon votre explication, il ne serait pas possible de dire par exemple, #if WIN32 || __CYGWIN__mais cela fonctionne comme prévu.
Ben Voigt
Je simplifiais. S'il y a un ou, il vérifiera si l'un des jetons est différent de zéro. De même, s'il y a un et, il vérifiera si les deux sont différents de zéro.
Steve Rowe
3

Les lignes commençant par un #sont des directives de préprocesseur . #if 0 [...] #endifles blocs ne parviennent pas au compilateur et ne génèrent aucun code machine.

Vous pouvez montrer ce qui se passe avec le préprocesseur avec un fichier source ifdef.cxx:

#if 0
This code will not be compiled
#else
int i = 0;
#endif

Running gcc -E ifdef.cxxvous montrera ce qui est compilé.

Vous pouvez choisir d'utiliser ce mécanisme pour empêcher qu'un bloc de code ne soit compilé pendant le cycle de développement, mais vous ne voudriez probablement pas l'archiver dans votre contrôle de source car il ajoute simplement du cran à votre code et réduit la lisibilité. Si c'est un morceau de code historique qui a été commenté, alors il devrait être supprimé: le contrôle de source contient l'historique, non?

De plus, la réponse peut être la même pour C et C ++, mais il n'y a pas de langage appelé C / C ++ et ce n'est pas une bonne habitude de faire référence à un tel langage.

Johnsyweb
la source
4
Quel est le problème de dire C / C ++ comme raccourci pour «C ou C ++»? Pensez-vous honnêtement que quelqu'un va être confus en pensant qu'il existe un langage appelé "C / C ++"?
Christopher Barber
1
@Chris: Les gens posent constamment des questions telles que "Comment faire X en C / C ++?" Ce qui est une question absurde; vous codez dans l'un ou l'autre, et si vous n'avez pas encore choisi, vous devriez être explicite sur ce fait. Donc, oui, les gens ne savent pas qu'il existe un langage appelé "C / C ++"
Dennis Zickefoose
1
Quelle déclaration absurde! Il y a des milliers de questions dont les réponses concernent à la fois C et C ++. N'oubliez pas que c'est un site pour poser des questions. Ce n'est pas parce que vous posez une question générale que vous ne savez pas quelle langue vous utilisez. Si vous pensez que c'est le cas, comme dans cette question, comment cela aide-t-il à spécifier C ou C ++? Pensez-vous qu'il serait utile que chaque question qui pourrait s'appliquer au C ou au C ++ soit posée deux fois?
Christopher Barber
@Christopher: Vous avez raison, il y a beaucoup de questions où les réponses sont tout aussi pertinentes pour C, C ++ et Objective-C (c'est l'une d'entre elles). Stack Overflow dispose d'un système de balisage pratique pour indiquer à quelles langues appartient une question. Comme @Dennis le mentionne, SO (et d'autres forums de programmation [forums?]) Il y a (trop) beaucoup de gens qui sont confus quant à la délimitation entre C et d'autres langages dérivés du C qui se réfèrent à ces langages de manière interchangeable comme C / C ++, ce qui en fait plus difficile de répondre à la question dans la langue appropriée.
Johnsyweb
2

Pas assez

int main(void)
{
   #if 0
     the apostrophe ' causes a warning
   #endif
   return 0;
}

Il affiche "tc: 4: 19: avertissement:" caractère de terminaison manquant "avec gcc 4.2.4

Arthur Kalliokoski
la source
2
Cet avertissement est généré par le préprocesseur, pas par le compilateur. Le compilateur ne voit que: # 1 "tc" # 1 "<built-in>" # 1 "<command-line>" # 1 "tc" int main (void) {return 0; }
Johnsyweb
0

C'est un moyen peu coûteux de commenter, mais je soupçonne que cela pourrait avoir un potentiel de débogage. Par exemple, supposons que vous ayez une construction qui génère des valeurs dans un fichier. Vous pourriez ne pas vouloir cela dans une version finale afin que vous puissiez utiliser le #if 0 ... #endif.

De plus, je soupçonne qu'une meilleure façon de le faire à des fins de débogage serait de faire:

#ifdef DEBUG
// output to file
#endif

Vous pouvez faire quelque chose comme ça et cela pourrait avoir plus de sens et tout ce que vous avez à faire est de définir DEBUG pour voir les résultats.

Daniel
la source