2010-06-03 2 views
15

Pourquoi les commentaires imbriqués sont-ils interdits en C++, Java malgré le fait que les commentaires imbriqués sont utiles, nets et élégants et peuvent être utilisés pour commenter des instructions qui ont des commentaires?Pourquoi les commentaires imbriqués sont-ils interdits?

+6

"fait"? Vraiment? –

Répondre

14

C et C++ le font pour faciliter l'analyse. De cette façon, quand ils frappent un début de commentaire de/*, l'analyseur peut balayer trivialement jusqu'à la fin. Dans le cas contraire, il faudrait configurer et maintenir une pile, puis signaler les erreurs si les jetons de commentaire ne sont pas appariés. Pour ce qui est de Java, la réponse est simple: la syntaxe de Java a été conçue pour émuler le C et le C++, pour inciter les gens à penser qu'il était tout aussi rapide (au début, Java était purement interprété). nécessaire pour obtenir une traction). Si les commentaires imbriqués étaient autorisés, il pourrait trébucher certains programmeurs en C, et beaucoup de messages de blog en colère seraient écrits!

+0

Pourquoi auriez-vous besoin d'une pile pour gérer les commentaires imbriqués? Maintenez simplement un compteur, en l'incrémentant chaque fois que vous rencontrez un '/ *' et en le décrémentant chaque fois que vous rencontrez un '* /'. Quand le compteur est supérieur à zéro, vous jetez tous les caractères que vous trouvez (tout en gardant la trace de '/ *' et '* /'); lorsque le compteur est à zéro, vous lisez normalement les jetons et les remettez à l'analyseur; Si le compteur devient négatif, vous signalez une discordance entre les délimiteurs de commentaires. Vous faites ceci pendant l'analyse lexicale, ainsi l'analyseur ne voit même jamais les commentaires. –

3

Conformance/compatibilité avec C.

+1

Est-ce que C n'a pas seulement utilisé le symbole de commentaire? Aussi, pourquoi Java devrait-il se conformer à la norme C? – tloach

+3

@tloach: '//' n'existe pas en C avant C99. – kennytm

+7

C utilisé à l'origine uniquement/* * /, et Java a été volontairement structuré après C (et C++) pour le rendre plus familier aux programmeurs existants. Conform est probablement trop fort d'un mot ici, mais je ne suis pas sûr de ce qui serait mieux. – ergosys

8

Au moins pour C++ qui est vrai qu'en partie, il n'y a pas de problème avec:

/* 
// 
// 
*/ 

Toutefois, si vous avez déjà eu un/* commentaire dans une section que vous voulez commentez vous pourriez être capable de le faire en l'entourant d'un #if 0 que je pense que beaucoup de compilateurs optimisent loin. Comme dans:

#if 0 
/* 

*/ 
#endif 
+1

TOUS les compilateurs optimisent cela, de la même manière qu'ils "optimisent" les inclusions multiples quand les gardes d'en-tête sont utilisés, car cela fait partie de l'étape de pré-traitement. –

+4

Les compilateurs ne verront pas ce bloc, le * préprocesseur * l'aura supprimé avant qu'un compilateur ne pose les yeux sur le code :). – Pieter

+0

@wowus: Oui, vous avez raison, bien sûr. Je pensais à 'if (0)' qui, selon moi, dépend du compilateur. –

3

Il est différent pour chaque langue (-famille) mais en général ils ne sont pas «interdits» mais simplement pas pris en charge. Les soutenir est un choix de conception.

Une des raisons du choix (pour les langues plus anciennes) a peut-être été la facilité d'analyse.

Remarque: Je me souviens d'un compilateur C++ dans lequel il était possible de les imbriquer. Il a été marqué comme «non standard».

2

Prenons l'exemple suivant:

/* This is a comment /* Nested Comments */ are not allowed. */ 

Tout ce qui se trouve entre /* et */ est traité comme un commentaire. Dans l'exemple ci-dessus de This jusqu'à Comments tout est traité comme des commentaires, y compris /*. Par conséquent, are not allowed. */ ne réside pas dans le commentaire. Il s'agit d'une erreur d'instruction C incorrecte.

Alors considèrent cet exemple:

// This is an /* valid */ comment 

Quelle que soit se trouve dans la ligne après // est traité comme commentaire. Puisque /* valid */ se trouve dans la même ligne après //, il est traité comme faisant partie du commentaire.

0

Dans les langages qui autorisent les commentaires de longueur arbitraire, il est très courant que les programmeurs commettent accidentellement des commentaires ou, dans de rares cas, "décommentent" dans plus ou moins de code que souhaité. Dans de nombreux cas, de telles erreurs conduisent à des erreurs de compilation, mais dans d'autres cas, elles peuvent aboutir à un code qui est simplement brisé. Avec les éditeurs de mise en évidence syntaxique modernes, une règle que chaque /* incrémenterait un compteur de commentaires imbriqués et chaque */ qui le décrémenterait pourrait ne pas causer trop de problèmes, mais sans coloration syntaxique même en essayant de comprendre quel code est commenté et quel code wasn Ça pourrait être un gros mal de tête.Si l'on était en train de concevoir un langage à partir de zéro, une bonne approche pourrait consister à spécifier des marques de début de commentaire et de fin de commentaire qui comprenaient une chaîne optionnelle, et demander au langage de faire en sorte que la chaîne la marque de fin de commentaire doit correspondre à la chaîne dans la marque de début de commentaire correspondante. En supposant que la syntaxe était <|String| et |String|>, un compilateur pouvait alors accepter <|1| <|2| |2|> |1|>, mais rejeter <|1| <|2| |1|> |2|>. Même si l'on préférait utiliser des directives #if plutôt que des commentaires, il serait utile de pouvoir attacher des marqueurs pour s'assurer que chaque directive d'extrémité correspondait à la directive de départ voulue.

-1

Le problème est que vous ne pouvez pas simplement "ignorer" les blocs. les blocs ont un nombre inconnu de blocs à l'intérieur d'eux, donc pour savoir quand ce bloc est complet, vous ne pouvez pas utiliser un langage régulier, vous devez utiliser une pile et parcourir chaque bloc jusqu'à ce que la pile soit vide, vous savez que le bloc est fait.

La raison pour laquelle vous ne pouvez pas ignorer les blocs est que l'expression rationnelle pour le bloc est seulement capable de correspondre à/* avec "le premier */il voit après" ou "le dernier */il voit après" ou "nth */il voit après".

Si nous allons avec le premier « */» jeton que nous voyons, nous pouvons avoir un code comme

/* 
    /* 

    */ 
    the compiler matched /* with */ and this line and the next one will confuse it. 
*/ 

Si nous allons avec le dernier jeton « */» nous voyons, nous avons un code où le compilateur va passer les choses entre le premier commentaire dans le fichier et le dernier commentaire de la fin du fichier. Dans ce cas, le code suivant sera analysé comme une chaîne vide.

/* 
    /* hello, world! */ 
*/ 
int main(int argc, char ** argv) { 
    return 0; 
} 
/* end of file */ 

Nous ne pouvons pas aller avec la troisième option de saut n blocs internes sans forcer tous les commentaires à avoir le nombre exact de la profondeur, sinon il ne trouvera pas le commentaire intérieur et se confondre.

En fait, il existe une quatrième option qui stipule explicitement qu'un commentaire peut être un seul commentaire, un commentaire à deux portées, un commentaire à trois portées, etc .; Mais cela est moche, et chaque niveau de profondeur nécessite une expression beaucoup plus longue, et cette approche limite les commentaires à une profondeur spécifique qui peut convenir à certaines personnes, et ne convient pas aux autres: Que faire si vous commentez un code qui a été commenté 3 fois?

La solution générale peut être mis en œuvre avec un pré-préprocesseur tels que:

<?php 
function stripComments($code) { 
    $stack = array(); 
    $codeOut = ''; 
    $stringStream = fopen('php://memory', 'r+'); 
    fwrite($stringStream, $code); 
    rewind($stringStream); 

    while (!feof($stringStream)) { 
     $ch = fgetc($stringStream); 

     $nextChar = fgetc($stringStream); 
     if ($nextChar === false) { 
      break; 
     } 

     if ($ch == '/' && $nextChar == '*') { 
      array_push($stack, '/*');   
     } else if ($ch == '*' && $nextChar == '/') { 
      if (count($stack) > 0) { 
       array_pop($stack); 
      } else { 
       die('cannot pop from empty stack'); 
      } 
     } else { 
      if (count($stack) == 0) { 
       $codeOut .= $ch; 
       fseek($stringStream, -1, SEEK_CUR); 
      } 
     }    

     $prevChar = $ch; 
    } 
    return $codeOut; 
}; 
?> 

Ce qui est un peu plus compliqué que ce que C utilise actuellement:

function stripComments($code) { 
    return preg_replace('/\/\*[^\*\/]*\*\//', '', $code); 
} 

Cela ne prend pas en considération /**/ bloque entre guillemets, une pile légèrement plus compliquée qui permet de distinguer entre "/ *" scope et "\" "est requise. 0 L'avantage d'avoir des commentaires dans les commentaires est que vous pouvez commenter des blocs qui contiennent des commentaires sans les supprimer manuellement, ce qui est particulièrement frustrant pour les blocs qui ont des commentaires sur chaque ligne.

Résumé: Cela peut être fait, mais la plupart des langages ne veulent pas traiter les commentaires comme s'ils étaient leurs propres étendues, car il faut plus d'efforts pour analyser.