Wird der Böse Zauber vom bösen Compiler übertrumpft?

7

Dies ist kein akademischer Code oder eine hypothetische Frage. Das ursprüngliche Problem bestand darin, Code von HP11 in HP1123 Itanium zu konvertieren. Im Grunde läuft es auf einen Kompilierungsfehler auf HP1123 Itanium hinaus. Es hat mir wirklich den Kopf verkratzt, wenn ich es zu Studienzwecken auf Windows vervielfältige. Ich habe alle außer den grundlegendsten Aspekten entfernt ... Möglicherweise müssen Sie die Steuerung D drücken, um ein Konsolenfenster zu verlassen, wenn Sie es wie folgt ausführen:

%Vor%

Hier ist die Ausgabe

%Vor%

Alles, was ich sagen kann, ist was zum Teufel? Ist es undefiniert, dies zu tun? Es ist die kontraintuitivste Sache, die ich für solch ein einfaches Beispiel gesehen habe.

Aktualisierung:

Tatsächlich nach dem Suchen nach einer Weile das Menü Debug & gt; & gt; Windows & gt; & gt; Demontage hatte genau die Optimierung, die unten beschrieben wurde.

%Vor%

Danke euch allen!

    
ojblass 03.04.2009, 02:20
quelle

5 Antworten

24

Sieht so aus, als würde der Compiler optimieren

%Vor%

in

%Vor%

seit Sie sagten dass IAMCONST ein const int ist.

Aber da du die Adresse von IAMCONST nimmst, muss sie irgendwo auf dem Stack liegen und die const ness kann nicht erzwungen werden, also der Speicher an dieser Stelle ( *pTOCONST ) ist doch veränderlich.

Kurz gesagt: Sie haben die const ness weggeworfen, tun Sie das nicht. Armes, wehrloses C ...

Nachtrag

Verwenden von GCC für x86, mit -O0 (keine Optimierungen), der generierten Assembly

%Vor%

kopiert von *(bp-12) auf dem Stapel zu printf 's Argumente. Verwenden Sie jedoch -O1 (sowie -Os , -O2 , -O3 und andere Optimierungsstufen),

%Vor%

Sie können deutlich sehen, dass stattdessen die Konstante 3 verwendet wird.

Wenn Sie Visual Studio CL.EXE verwenden, deaktiviert /Od die Optimierung. Dies variiert von Compiler zu Compiler.

Seien Sie gewarnt, dass die C-Spezifikation zulässt, dass der C-Compiler davon ausgeht, dass das Ziel eines int * -Zeigers niemals überlappt der Speicherort eines const int , also sollten Sie das überhaupt nicht tun, wenn Sie vorhersehbares Verhalten wollen.

    
ephemient 03.04.2009, 02:27
quelle
6

Der konstante Wert IAMCONST wird in den printf-Aufruf eingebunden.

Was Sie tun, ist bestenfalls falsch und wahrscheinlich vom C ++ - Standard undefiniert. Mein rate ist, dass der C ++ - Standard den Compiler frei lässt, ein const-Primitiv zu inline zu schreiben, das lokal für eine Funktionsdeklaration ist. Der Grund dafür ist, dass der Wert nicht geändert werden kann.

Andererseits ist es C ++, wo es sehr unterschiedliche Wörter geben kann und kann.

    
JaredPar 03.04.2009 02:25
quelle
4

Sie haben Glück, dass der Compiler die Optimierung durchführt. Eine alternative Behandlung bestünde darin, die Konstante const in den Nur-Lese-Speicher zu setzen, woraufhin der Versuch, den Wert zu ändern, einen Core-Dump verursachen würde.

    
Jonathan Leffler 03.04.2009 03:00
quelle
2

Schreiben in ein konstantes Objekt durch einen Cast, der const entfernt, ist undefiniertes Verhalten - also an dem Punkt, an dem Sie dies tun:

%Vor%

Alle Wetten sind aus.

Aus dem C ++ - Standard 7.1.5.1 (Die cv-Qualifikationsmerkmale):

  

Mit Ausnahme dessen, dass ein beliebiges deklariertes Klasse-Member (7.1.1) geändert werden kann, jeder Versuch, ein const   Objekt während seiner Lebensdauer (3.8) führt zu undefiniertem Verhalten.

Aus diesem Grund kann der Compiler davon ausgehen, dass sich der Wert von IAMCONST nicht ändert, sodass der Zugriff auf den tatsächlichen Speicher optimiert werden kann. Wenn die Adresse des const-Objekts nie genommen wird, kann der Compiler den gesamten Speicher für das Objekt eliminieren.

Beachten Sie auch (wieder in 7.1.5.1):

  

Eine Variable eines nichtflüchtigen Const-qualifizierten Integral- oder Enumerationstyps, die durch einen ganzzahligen konstanten Ausdruck initialisiert wird, kann in Integralkonstantenausdrücken verwendet werden (5.19).

Dies bedeutet, dass IAMCONST in Kompilierungskonstantenausdrücken verwendet werden kann (z. B. um einen Wert für eine Enumeration oder die Größe eines Arrays bereitzustellen). Was würde es bedeuten, das zur Laufzeit zu ändern?

    
Michael Burr 03.04.2009 04:22
quelle
-3

Es spielt keine Rolle, ob der Compiler optimiert wird oder nicht. Sie haben nach Ärger gefragt und Sie haben Glück, dass Sie sich selbst die Mühe gemacht haben, anstatt darauf zu warten, dass die Kunden Ihnen das melden.

"Alles was ich sagen kann, ist was zum Teufel? Ist es unbestimmt das zu tun? Es ist das widersinnigste was ich für solch ein einfaches Beispiel gesehen habe."

Wenn du das wirklich glaubst, dann musst du zu einer Sprache wechseln, die du verstehen kannst, oder den Beruf wechseln. Nutzen Sie C und C ++ oder C # für sich und Ihre Kunden.

%Vor%

Du hast es gesagt.

%Vor%

Erraten Sie, warum der Compiler sich beschwert hat, wenn Sie Ihre böse Besetzung ausgelassen haben. Der Compiler hat vielleicht die Wahrheit gesagt, bevor Sie ihn belogen haben.

"Wird der Böse Zauber vom bösen Compiler übertrumpft?"

Nein. Die böse Besetzung wird von sich selbst übertrumpft. Ob dein Compiler versuchte, dir die Wahrheit zu sagen, der Compiler war nicht böse.

    
Windows programmer 03.04.2009 05:03
quelle

Tags und Links