Heim > Backend-Entwicklung > C++ > Zeigt die Funktionsverkettung in der „Programmiersprache C' nicht spezifiziertes Verhalten?

Zeigt die Funktionsverkettung in der „Programmiersprache C' nicht spezifiziertes Verhalten?

Barbara Streisand
Freigeben: 2024-10-23 18:19:25
Original
457 Leute haben es durchsucht

Does Function Chaining in

Zeigt ein Codeausschnitt in „Die Programmiersprache C“ undefiniertes Verhalten?

Der betreffende C-Code, wie von Bjarne Stroustrup in der 4. Auflage von „ Die Programmiersprache C verwendet Funktionsverkettung, um eine Zeichenfolge zu ändern:

<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>
Nach dem Login kopieren

Dieser Code demonstriert die Verkettung von replace()-Operationen, um die Zeichenfolge s zu ändern. Es wurde jedoch beobachtet, dass dieser Code bei verschiedenen Compilern wie GCC, Visual Studio und Clang ein unterschiedliches Verhalten aufweist.

Analyse

Der Code mag zwar unkompliziert erscheinen, beinhaltet jedoch eine nicht spezifizierte Reihenfolge der Auswertung, insbesondere für Unterausdrücke, die Funktionsaufrufe beinhalten. Obwohl es kein undefiniertes Verhalten hervorruft (da alle Nebenwirkungen innerhalb von Funktionsaufrufen auftreten), zeigt es unspezifisches Verhalten.

Das Hauptproblem besteht darin, dass die Reihenfolge der Auswertung von Unterausdrücken, wie z. B. s.find( „even“) und s.find(“ don't“), ist nicht explizit definiert. Diese Unterausdrücke können entweder vor oder nach dem ersten Aufruf von s.replace(0, 4, "") ausgewertet werden, was sich auf das Ergebnis auswirken kann.

Wenn wir die Reihenfolge der Auswertung für das Code-Snippet untersuchen:

s.replace(0, 4, "").replace(s.find("even"), 4, "only").replace(s.find(" don't"), 6, "");
Nach dem Login kopieren

Wir können sehen, dass die folgenden Unterausdrücke unbestimmt sequenziert sind (angezeigt durch die Zahlen in Klammern):

  • s.replace(0, 4, "") (1)
  • s.find("even") (2)
  • s.replace(s.find("even"), 4, "only") (3)
  • s.find(" don't") (4)
  • s.replace(s.find(" don't"), 6, "") (5)

Die Ausdrücke in jedem Klammerpaar sind geordnet (z. B. 2 steht vor 3), sie können jedoch in unterschiedlicher Reihenfolge relativ zueinander ausgewertet werden. Konkret liegt die Unbestimmtheit zwischen den Ausdrücken 1 und 2 sowie zwischen 1 und 4.

Compiler-Unterschiede

Die beobachteten Diskrepanzen im Compiler-Verhalten können auf die jeweils unterschiedlichen Auswertungsreihenfolgen zurückgeführt werden Compiler. In einigen Fällen werden die Aufrufe von replace() auf eine Weise ausgewertet, die zum erwarteten Verhalten führt, während in anderen Fällen die Auswertungsreihenfolge die Zeichenfolge auf unerwartete Weise ändert.

Bedenken Sie zur Veranschaulichung Folgendes:

  • In einigen Implementierungen, wie z. B. Clang, wird replace(0, 4, "") vor find("even") und find("don't") ausgewertet. Dadurch wird sichergestellt, dass die nachfolgenden Ersetzungsaufrufe mit der geänderten Zeichenfolge arbeiten und das richtige Ergebnis liefern.
  • In anderen Implementierungen wie GCC und Visual Studio finden find("even") und find("don't") kann vor replace(0, 4, "") ausgewertet werden. Dies kann zu falschen Ergebnissen führen, da die Suchaufrufe mit der ursprünglichen, unveränderten Zeichenfolge arbeiten und möglicherweise andere Positionen als beabsichtigt finden.

Spezifiziertes vs. nicht spezifiziertes Verhalten

Das ist wichtig zu beachten Dieser Code ruft kein undefiniertes Verhalten hervor. Zu undefiniertem Verhalten gehört typischerweise der Zugriff auf nicht initialisierte Variablen oder der Versuch, auf den Speicher außerhalb seiner Grenzen zuzugreifen. In diesem Fall treten alle Nebenwirkungen innerhalb von Funktionsaufrufen auf und der Code greift nicht auf ungültige Speicherorte zu.

Der Code weist jedoch ein nicht spezifiziertes Verhalten auf, was bedeutet, dass die genaue Reihenfolge von Die Auswertung von Unterausdrücken ist im C-Standard nicht definiert. Dies kann zu unterschiedlichen Ergebnissen auf verschiedenen Compilern oder sogar zu unterschiedlichen Ausführungen desselben Programms führen.

Vorgeschlagene Änderungen

Das C-Standardkomitee hat dieses Problem erkannt und Änderungen vorgeschlagen, um die Reihenfolge der Ausdrucksauswertung zu verfeinern idiomatisches C . Vorgeschlagene Änderungen an [expr.call]p5 in C 20 geben an, dass „der Postfix-Ausdruck vor jedem Ausdruck in der Ausdrucksliste und jedem Standardargument sequenziert wird“, wodurch das nicht spezifizierte Verhalten in diesem Code beseitigt würde.

Das obige ist der detaillierte Inhalt vonZeigt die Funktionsverkettung in der „Programmiersprache C' nicht spezifiziertes Verhalten?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:php
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage