Zwei String-Literale haben denselben Zeigerwert?

7

Wenn ich dieses Programm mit MinGW starte, wird die Ausgabe als "="

ausgegeben %Vor%

Logischerweise sollte es! = sein, denn das sind Zeiger, die auf verschiedene Speicherstellen zeigen. Wenn ich diesen Code in meinem Turbo C ++ ausführe, bekomme ich! =

    
Vipul bhojwani 22.11.2012, 15:11
quelle

5 Antworten

13

Sie haben Recht, dass sie Zeiger sind. Ob sie jedoch auf unterschiedliche Standorte zeigen oder nicht, hängt von der Implementierung ab. Es ist durchaus zulässig, dass ein Compiler ein String-Literal nur einmal speichert und seine Adresse überall dort verwendet, wo es im Code verwendet wird.

    
Angew 22.11.2012 15:14
quelle
8

Es gibt keine Garantie, dass die zwei Zeiger auf verschiedene Speicherorte zeigen. Vielleicht liegt es an Optimierungen oder der Compiler verwendet seine eigenen Regeln ... das Verhalten ist "Implementation De fi ned".

Gemäß dem Standard (C ++ 11 §2.14.5 String Literals):

  

Gibt an, ob alle Zeichenfolgenliterale unterschiedlich sind (also gespeichert sind)   in nicht überlappenden Objekten) ist die Implementierung de fi niert.

    
timothyqiu 22.11.2012 15:32
quelle
2

Dies ist ein erwartetes Ergebnis. Sie können dies überprüfen, indem Sie sich die zugrunde liegende Baugruppe ansehen. Zum Beispiel, wenn ich mit:

baue %Vor%

dann können Sie in der Dateiausgabe (ptr.s) Folgendes sehen:

%Vor%

Ich habe die zwei Schlüssel-Bits kommentiert - nur eine Erscheinung von 'Hallo' ist im rdata-Abschnitt des zugrunde liegenden Codes, und Sie können sehen, str1 und str2 sind gegen Ende gesetzt, beide auf das gleiche Label: %Code%. Dies ist "Hallo" ist ein String-Literal und, was wichtig ist, ist konstant .

Wie andere darauf hingewiesen haben, ist dies unter den Standards vollkommen legal.

    
Chris J 22.11.2012 15:58
quelle
2

Der Typ eines Zeichenfolgenliterals wie "Hello" ist Array von const char . Daher verweisen Sie zwei Zeiger auf etwas, das sich niemals ändern darf.

Der C ++ - Standard gibt Compilern die Freiheit, identische konstante Werte zusammenzuführen (beachten Sie, dass Compiler dazu nicht erforderlich sind ).

Related: Die Deklarationen sind daher ungültig und müssen wie folgt geändert werden:

%Vor%

oder wenn Sie möchten

%Vor%

was beim Lesen von rechts nach links gut aussieht:

%Vor%

.

    
Sebastian Mach 22.11.2012 16:13
quelle
0

char *str1 = "Hello"; - diese Zeile ist zwar erlaubt (von vielen Compilern), ist aber eine schlechte Idee. Es ist im Grunde nur für Rückwärtskompatibilität mit C erlaubt, und das Schreiben in * str1 führt zu undefiniertem Verhalten. Ich würde empfehlen, die Compilereinstellung zu finden, die Ihnen Warnungen gibt, wenn Sie dies tun, und wenn Ihr Compiler solche Warnungen nicht findet, einen neuen Compiler zu finden.

Der C ++ - Standard gibt Compilern und Ausführungsumgebungen lächerliche Freiheitsgrade, wo "String literals" gespeichert sind. Sie könnten einen Zeiger auf den "literal" -Teil von "String literals" als Zeigerwert für "literal" verwenden und sie im Arbeitsspeicher speichern, in dem Sie segfault geben würden, wenn Sie versuchen, sie zu bearbeiten, ist nicht unerwartet.

Beachten Sie, dass char buf1[] = "Hello"; etwas grundlegend anderes tut als char* str1 = "Hello"; : Es initialisiert tatsächlich den Puffer buf1 mit den Zeichen {'H','e','l','l','o','%code%'} .

    
Yakk 22.11.2012 15:37
quelle

Tags und Links