Le code C en question, tel que fourni par Bjarne Stroustrup dans la 4e édition de " Le langage de programmation C" utilise le chaînage de fonctions pour modifier une chaîne :
<code class="cpp">void f2() { std::string s = "but I have heard it works even if you don't believe in it"; s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don't"), 6, ""); assert(s == "I have heard it works only if you believe in it"); }</code>
Ce code démontre le chaînage des opérations replace() pour modifier la chaîne s. Cependant, il a été observé que ce code présente un comportement différent selon les différents compilateurs, tels que GCC, Visual Studio et Clang.
Bien que le code puisse paraître simple, il implique un ordre non spécifié d'évaluation, en particulier pour les sous-expressions qui impliquent des appels de fonction. Bien qu'il n'invoque pas de comportement indéfini (puisque tous les effets secondaires se produisent dans les appels de fonction), il présente un comportement non spécifié.
Le problème clé est que l'ordre d'évaluation des sous-expressions, telles que s.find( "even") et s.find(" don't"), n'est pas explicitement défini. Ces sous-expressions peuvent être évaluées avant ou après l'appel initial à s.replace(0, 4, ""), ce qui peut avoir un impact sur le résultat.
Si nous examinons l'ordre d'évaluation de l'extrait de code :
s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don't"), 6, "");
On peut voir que les sous-expressions suivantes sont séquencées de manière indéterminée (indiquées par les chiffres entre parenthèses) :
Les expressions contenues dans chaque paire de parenthèses sont ordonnées (par exemple, 2 précède 3), mais elles peuvent être évaluées dans des ordres différents les unes par rapport aux autres. Plus précisément, l'indétermination se situe entre les expressions 1 et 2, ainsi qu'entre 1 et 4.
Les écarts observés dans le comportement du compilateur peuvent être attribués aux différents ordres d'évaluation choisis par chacun compilateur. Dans certains cas, les appels à replace() sont évalués d'une manière qui aboutit au comportement attendu, tandis que dans d'autres cas, l'ordre d'évaluation modifie la chaîne de manière inattendue.
Pour illustrer, considérons ce qui suit :
Il est important de noter que ce code n'invoque pas un comportement indéfini. Un comportement non défini implique généralement l'accès à des variables non initialisées ou la tentative d'accès à la mémoire en dehors de ses limites. Dans ce cas, tous les effets secondaires se produisent dans les appels de fonction et le code n'accède pas aux emplacements mémoire non valides.
Cependant, le code présente un comportement non spécifié, ce qui signifie que l'ordre exact de l'évaluation des sous-expressions n'est pas définie par le standard C. Cela peut conduire à des résultats différents selon les compilateurs ou même à différentes exécutions du même programme.
Le comité de standard C a reconnu ce problème et a proposé des modifications pour affiner l'ordre d'évaluation des expressions pour idiomatique C. Les modifications proposées pour [expr.call]p5 dans C 20 spécifient que "l'expression postfixée est séquencée avant chaque expression de la liste d'expressions et tout argument par défaut", ce qui éliminerait le comportement non spécifié dans ce code.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!