Quelle est exactement la règle du «comme si»?

89

Comme le titre l'indique,

Quelle est exactement la règle du «comme si»?

Une réponse typique que l'on obtiendrait est:

La règle qui autorise toutes les transformations de code qui ne changent pas le comportement observable du programme

De temps en temps, nous continuons à obtenir des comportements de certaines implémentations qui sont attribués à cette règle. Plusieurs fois à tort. Alors, quelle est exactement cette règle. La norme ne mentionne pas clairement cette règle sous la forme d'un article ou d'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.

Alok Save
la source
2
Il fait référence à la machine abstraite.
Alexey Frunze
" Marquer ceci comme C et C ++ à la fois, car il est pertinent pour les deux langues " C'est pertinent dans n'importe quel langage.
curiousguy
@AlexeyFrunze " Il se réfère à la machine abstraite " Il se réfère à l'état de la "machine abstraite" étant un outil et non une fin, et n'étant pas pertinent en terme de conformité, parce que c'est "abstrait" qui est un outil de spécification pas réel.
curiousguy

Réponses:

98

Quelle est la règle du « comme si »?

Le " comme si règle » 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.

Le but 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 le standard C ++ en termes de machine abstraite.


Où la norme introduit-elle cette règle?

La norme C ++ 11 introduit la règle " comme si " au paragraphe 1.9 / 1:

Les descriptions sémantiques de la présente Norme internationale définissent une machine abstraite paramétrée non déterministe. 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 nécessaires pour émuler (uniquement) le comportement observable de la machine abstraite comme expliqué ci-dessous.

En outre, une note explicative ajoute:

Cette disposition est parfois appelée la règle du «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ù cela peut être déterminé à 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.


Que prescrit la règle exactement?

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 la machine abstraite avec le même programme et la même entrée . Cependant, si une telle exécution contient une opération indéfinie, la présente Norme internationale n'impose aucune exigence sur 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 vaut la peine de souligner que cette contrainte s'applique uniquement lors de "l'exécution d'un programme bien formé" , et que les résultats possibles de l'exécution d'un programme qui contient un comportement non défini ne sont pas contraints. Ceci est également expliqué 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 la tentative de modification d'un objet const). [Remarque: La présente Norme internationale n'impose aucune exigence sur le comportement des programmes qui contiennent un comportement indéfini . —End note]

Enfin, concernant la définition du " comportement observable ", le paragraphe 1.9 / 8 se lit comme suit:

Les moindres exigences sur une implémentation conforme sont:

- L'accès aux objets volatils est évalué strictement selon les règles de la machine abstraite.

- A 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 avoir lieu de manière à ce que la sortie d'invite soit effectivement délivrée avant qu'un programme n'attende une entrée. Ce qui constitue un dispositif interactif est défini par l'implémentation.

Celles-ci sont désignées collectivement sous le nom de comportement observable du programme . [ Note : Des correspondances plus strictes entre la sémantique abstraite et réelle peuvent être définies par chaque implémentation. - note de fin ]


Y a-t-il des situations où cette règle ne s'applique pas?

Au meilleur de ma connaissance, la seule exception à la règle " as-if " est l'élision de copie / déplacement, qui est autorisée même si le constructeur de copie, le constructeur de déplacement ou le destructeur d'une classe ont des effets secondaires. Les conditions exactes à cet effet sont spécifié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 . [...]

Andy Prowl
la source
2
J'ai vu cette citation. Ce qui n'est pas clair, c'est la définition du comportement observable. Qu'est-ce qui est exactement qualifié de comportement observable? L'élision de copie étant une exception à la règle du «comme si» est assez bien connue et ne fait pas vraiment partie de ma question.
Alok Enregistrer
2
@AlokSave: Eh bien dans le standard C, nous voyons "Accéder à un objet volatil, modifier un objet, modifier un fichier ou appeler une fonction qui effectue l'une de ces opérations sont tous des effets secondaires". Il y a probablement quelque chose d'équivalent dans le (s) standard (s) C ++. De manière informelle, je suppose que "tout ce qui change son interaction avec le monde extérieur".
Oliver Charlesworth
1
Tout comportement qui change l'état de la machine abstraite (donc, quelque chose qui change une variable transmise ou une variable globale, ou lit et écrit sur des périphériques d'E / S).
Mats Petersson
1
Cela signifie-t-il que la suppression d'une boucle infinie qui ne fait rien est autorisée, tant que rien d'observable ne se produit par la suite?
harold
5
Un point à noter en particulier est qu'il ne s'applique qu'aux programmes juridiques . Tout ce qui invoque un comportement indéfini est explicitement hors de toute couverture.
vonbrand
15

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 as-if est dans C11 5.1.2.3p4 et p6 :

  1. 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 déduire que sa valeur n'est pas utilisée et qu'aucun effet secondaire nécessaire n'est produit (y compris ceux causés par l'appel d'une fonction ou l'accès à un objet volatile).

  2. [...]

  3. Les moindres exigences sur une implémentation conforme sont:

    • Accès à volatile objets sont évalués strictement selon les règles de la machine abstraite.
    • A 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é en 7.21.3 . L'intention de ces exigences est que la sortie sans tampon ou avec tampon de ligne apparaisse dès que possible, afin de garantir que les messages d'invite apparaissent réellement avant qu'un programme n'attende une entrée.

     

    C'est le comportement observable du programme.

Antti Haapala
la source
-1

En C, C ++, Ada, Java, SML ... dans tout langage de programmation bien spécifié en décrivant le (s) comportement (s) (généralement de nombreux possibles, non déterministes) d'un programme (exposé à une série d'interactions sur les ports d'E / S) , il n'y a pas de règle du `` comme si '' distincte .

Un exemple de règle distincte est celle qui dit qu'une division par zéro lève une exception (Ada, Caml) ou un déréférencement nul lève une exception (Java). Vous pourriez changer la règle pour spécifier autre chose et vous vous retrouveriez avec une langue différente (que certains appelleraient plutôt un "dialecte" (*). Une règle distincte est là pour spécifier certaines utilisations distinctes d'un langage de programmation comme un les règles grammaticales couvrent certaines constructions de syntaxe.

(*) Un dialecte selon certains linguistes est une langue avec une "armée". dans ce contexte, cela pourrait signifier un langage de programmation sans comité et une industrie spécifique d'éditeurs de compilateurs.

La règle as-if n'est pas une règle distincte ; elle ne couvre aucun programme en particulier et 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 portable (universellement) défini, en terme d'interactions visibles d'une exécution du programme avec le monde "extérieur".

Le monde externe peut être des interfaces d'E / S (stdio), une interface graphique, voire un interpréteur interactif qui produit la valeur résultante d'un pur langage applicatif. En C et C ++, cela inclut les accès (vaguement spécifiés) aux objets volatils, ce qui est une autre façon de dire que certains objets à un moment donné doivent être représentés en mémoire strictement selon l'ABI (Application Binary Interface) sans jamais mentionner l'ABI explicitement.

La définition de ce qu'est une trace d'exécution , également appelée comportement visible ou observable, définit ce que l'on entend par "règle comme si". La règle as-si tente de l'expliquer, mais ce faisant, elle confond les gens plus qu'elle ne clarifie les choses car elle donne l'expression d'être une règle sémantique supplémentaire donnant plus de marge de manœuvre à l'implémentation.

Résumé:

  • La règle dite "as-if" ne relâche aucune contrainte sur les implémentations.
  • Vous ne pouvez pas supprimer la règle as-if dans un langage de programmation spécifié en terme de comportement visible (traces d'exécution composées pour l'interaction avec le monde externe) pour obtenir un dialecte distinct.
  • Vous ne pouvez pas ajouter la règle as-if à un langage de programmation non spécifié en terme de comportement visible.
curieux
la source
Si les gens pensent que je me trompe, et qu'il existe une «règle comme si» distincte, pourquoi n'essaient-ils pas de décrire une variante de C ++ (un dialecte) sans cette «règle»? Que signifierait la spécification C ++ sans elle? Il serait absolument impossible de dire si un compilateur est conforme. Ou même définir la conformité.
curiousguy le