Comme le titre l'indique,
Une réponse typique que l'on obtiendrait serait:
La règle qui autorise toutes les transformations de code qui ne modifient pas le comportement observable du programme
De temps en temps, nous continuons à obtenir des comportements de certaines implémentations qui sont attribuées à cette règle. Plusieurs fois à tort. Alors, quelle est exactement cette règle. La norme ne mentionne pas clairement cette règle comme une section ou un paragraphe, alors qu'est-ce qui relève exactement de cette règle? Cela me semble être une zone grise qui n'est pas définie en détail par la norme. Quelqu'un peut-il élaborer sur les détails en citant les références de la norme?
Remarque: baliser ceci comme C et C++ à la fois, car il est pertinent pour les deux langages.
La règle " comme si " définit essentiellement les transformations qu'une implémentation est autorisée à effectuer sur un programme C++ légal. En bref, toutes les transformations qui n'affectent pas " le comportement observable d'un programme " (voir ci-dessous pour une définition précise) sont autorisées.
L'objectif est de donner aux implémentations la liberté d'effectuer des optimisations tant que le comportement du programme reste conforme à la sémantique spécifiée par la norme C++ en termes de machine abstraite.
La norme C++ 11 introduit la règle " comme si " dans le paragraphe 1.9/1:
Les descriptions sémantiques de la présente Norme internationale définissent une machine abstraite non déterministe paramétrée. La présente Norme internationale n'impose aucune exigence sur la structure des implémentations conformes. En particulier, ils n'ont pas besoin de copier ou d'émuler la structure de la machine abstraite. Au contraire, des implémentations conformes sont requises pour émuler (uniquement) le comportement observable de la machine abstraite comme expliqué ci-dessous.
En outre, une note de bas de page explicative ajoute:
Cette disposition est parfois appelée la règle "comme si", car une mise en œuvre est libre de ne pas tenir compte de toute exigence de la présente Norme internationale tant que le résultat est comme si l'exigence avait été respectée, dans la mesure où peut être déterminée à partir du comportement observable du programme. Par exemple, une implémentation réelle n'a pas besoin d'évaluer une partie d'une expression si elle peut en déduire que sa valeur n'est pas utilisée et qu'aucun effet secondaire affectant le comportement observable du programme n'est produit.
Le paragraphe 1.9/5 précise en outre:
Une implémentation conforme exécutant un programme bien formé produira le même comportement observable que l'une des exécutions possibles de l'instance correspondante de l'abstrait machine avec le même programme et la même entrée. Cependant, si une telle exécution contient une opération non définie, la présente Norme internationale n'impose aucune exigence à l'implémentation exécutant ce programme avec cette entrée (pas même en ce qui concerne les opérations précédant la première opération non définie).
Il convient de souligner que cette contrainte s'applique uniquement lorsque "exécute un programme bien formé" , et que les résultats possibles de l'exécution d'un programme contenant un comportement indéfini sont sans contrainte. Cela est également explicité au paragraphe 1.9/4:
Certaines autres opérations sont décrites dans la présente Norme internationale comme non définies (par exemple, l'effet de tenter de modifier un objet const). [Remarque: La présente Norme internationale n'impose aucune exigence sur le comportement des programmes qui contiennent un comportement non défini. —Fin note]
Enfin, concernant la définition du " comportement observable ", le paragraphe 1.9/8 se lit comme suit:
Les exigences minimales sur une implémentation conforme sont:
- L'accès aux objets volatils est évalué strictement selon les règles de la machine abstraite.
- À la fin du programme, toutes les données écrites dans des fichiers doivent être identiques à l'un des résultats possibles que l'exécution du programme selon la sémantique abstraite aurait produit.
- La dynamique d'entrée et de sortie des dispositifs interactifs doit se dérouler de telle manière qu'une invite de sortie soit réellement délivrée avant qu'un programme n'attende l'entrée. Ce qui constitue un appareil interactif est défini par l'implémentation.
Ceux-ci sont collectivement appelés le comportement observable du programme. [ Remarque : Des correspondances plus strictes entre la sémantique abstraite et réelle peuvent être définies par chaque implémentation. - note de fin ]
À ma connaissance, la seule exception à la règle " comme si " était la copie/déplacement d'élision, qui est autorisée même si le constructeur de copie , déplacer le constructeur ou le destructeur d'une classe ont des effets secondaires. Les conditions exactes sont précisées au paragraphe 12.8/31:
Lorsque certains critères sont remplis, une implémentation est autorisée à omettre la construction copier/déplacer d'un objet de classe, même si le constructeur sélectionné pour l'opération de copie/déplacement et/ou le destructeur de l'objet ont des effets secondaires =. [...]
En C11, la règle n'est jamais appelée par ce nom. Cependant C, tout comme C++, définit le comportement en termes de machine abstraite. La règle comme si était dans C11 5.1.2.3p4 et p6 :
Dans la machine abstraite, toutes les expressions sont évaluées comme spécifié par la sémantique. Une implémentation réelle n'a pas besoin d'évaluer une partie d'une expression si elle peut en déduire que sa valeur n'est pas utilisée et qu'aucun effet secondaire nécessaire n'est produit (y compris ceux provoqués par l'appel d'une fonction ou l'accès à un objet volatil)
[...]
Les exigences minimales sur une implémentation conforme sont:
- Les accès aux objets
volatile
sont évalués strictement selon les règles de la machine abstraite.- À la fin du programme, toutes les données écrites dans des fichiers doivent être identiques au résultat que l'exécution du programme selon la sémantique abstraite aurait produit.
- La dynamique d'entrée et de sortie des dispositifs interactifs doit avoir lieu comme spécifié dans 7.21. . Le but de ces exigences est que la sortie non tamponnée ou mise en mémoire tampon de ligne apparaisse dès que possible, pour garantir que les messages d'invite apparaissent réellement avant qu'un programme n'attende l'entrée.
C'est le comportement observable du programme.
En C, C++, Ada, Java, SML ... dans n'importe quel langage de programmation bien spécifié en décrivant les comportements (généralement nombreux possibles, non déterministes) d'un programme (exposés à une série d'interactions sur les ports d'E/S) , il n'y a pas de règle as-if distincte.
Un exemple de règle distincte est celle qui dit qu'une division par zéro déclenche une exception (Ada, Caml) ou qu'une déréférence nulle déclenche une exception (Java ). Vous pourriez changer la règle pour spécifier quelque chose d'autre et vous vous retrouveriez avec une langue différente (que certaines personnes préfèrent appeler un "dialecte" (*) . Une règle distincte est là pour spécifier certaines utilisations distinctes d'un langage de programmation comme une couverture de règles grammaticales distinctes certaines constructions de syntaxe.
(*) Un dialecte selon certains linguistes est une langue à "armée". dans ce contexte, cela pourrait signifier un langage de programmation sans comité et sans une industrie spécifique des éditeurs de compilateurs.
La règle comme si n'était pas une règle distincte ; il ne couvre aucun programme en particulier et ce n'est même pas une règle qui pourrait être discutée, supprimée ou modifiée de quelque manière que ce soit: la soi-disant "règle" réitère simplement que la sémantique du programme est définie, et ne peut être défini que de manière portative (universelle), en termes d'interactions visibles d'une exécution du programme avec le monde "extérieur".
Le monde extérieur peut être des interfaces d'E/S (stdio), une interface graphique, voire un interpréteur interactif qui génère la valeur résultante d'un langage applicatif pur. En C et C++, il inclut les accès (vaguement spécifiés) aux objets volatils, ce qui est une autre façon de dire que certains objets à un point donné doivent être représentés en mémoire strictement selon l'ABI (Application Binary Interface) sans jamais mentionner explicitement l'ABI.
La définition de ce qui est une trace d'exécution, également appelée comportement visible ou observable, définit ce que l'on entend par "règle as-if". La règle de simulation essaie de l'expliquer, mais ce faisant, elle embrouille les gens plus qu'elle ne clarifie les choses car elle donne l'expression d'être un élément supplémentaire. règle sémantique donnant plus de latitude à l'implémentation.
Résumé: