2012-11-22 6 views
7

Wenn ich dieses Programm mit MinGW laufen, im immer Ausgang als „=“Zwei String-Literale haben denselben Zeigerwert?

#include<iostream> 

using namespace std; 

int main() 
{ 
char *str1 = "Hello"; 
char *str2 = "Hello"; 

if(str1==str2) 
cout<<"="; 
else 
cout<<"!="; 


return 0; 
} 

jedoch logisch, sollte es sein! =, Coz diese sind Zeiger und sie zeigen auf unterschiedliche Speicherplätze. Wenn ich diesen Code in meinem Turbo C++ ausführe, bekomme ich! =

+2

Haben Sie die Optimierungen deaktiviert? –

+9

"und sie verweisen auf verschiedene Speicherorte" ... nun, es stellt sich heraus, dass sie tatsächlich auf den gleichen Ort zeigen. Dies ist erlaubt. –

+3

Die zwei backquotes im Quellcode sollten verhindern, dass sie kompiliert werden (und bei einem konformen C++ 11-Compiler sollte das Fehlen von "const" die Kompilierung verhindern). –

Antwort

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.

8

Es gibt keine Garantie, dass die beiden Zeiger auf unterschiedliche Speicherorte zeigen. Vielleicht liegt es daran, dass Optimierungen oder der Compiler eigene Regeln verwendet ... das Verhalten ist "Implementation De fi ned".

Nach der Norm (C++ 11 §2.14.5 Zeichenfolgenliteralen):

Ob alle Stringliterale verschieden sind (dh, werden gespeichert in nicht überlappenden Objekten) wird definiert Implementierung de fi.

0

char *str1 = "Hello"; - diese Zeile, obwohl erlaubt (von vielen Compilern), ist eine schlechte Idee, tatsächlich zu tun. 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 Compiler-Einstellung zu finden, die Ihnen Warnungen gibt, wenn Sie dies tun, und wenn Ihr Compiler solche Warnungen nicht hat, einen neuen Compiler zu finden.

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

Beachten Sie, dass char buf1[] = "Hello"; tut etwas grundsätzlich anderes als char* str1 = "Hello";: es initialisiert tatsächlich den Puffer buf1 mit den Zeichen {'H','e','l','l','o','\0'}.

+0

Der Standard definiert 'char * str =" Hallo ";' als ungültig. Wenn Compiler es noch unterstützen, ist es für die Kundenbetreuung, aber gegen den Standard. –

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 bauen:

g++ -S ptr.c 

dann können Sie die folgenden in der Datei ausgegeben (ptr.s) siehe:

 .file "ptr.c" 
     .def ___main;  .scl 2;  .type 32;  .endef 
     .section .rdata,"dr" 
LC0: 
     .ascii "Hello\0"    ; Note - "Hello" only appears once in 
             ; this data section! 
LC1: 
     .ascii "=\0" 
LC2: 
     .ascii "!=\0" 
     .text 
.globl _main 
     .def _main; .scl 2;  .type 32;  .endef 
_main: 
     [... some stuff deleted for brevity ...] 
LCFI5: 
     call ___main 
     movl $LC0, -12(%ebp)  ; This sets str1 
     movl $LC0, -8(%ebp)   ; This sets str2 
     movl -12(%ebp), %eax 

ich die beiden Tastenbits kommentiert haben - nur ein Aussehen von 'Hallo' ist in der rdata Abschnitt des zugrunde liegenden Codes, und Sie können sehen, str1 und str2 sind gegen Ende festgelegt, beide auf das gleiche Label: LC0. Dies ist "Hallo" ist ein String-Literal und, was wichtig ist, ist Konstante.

Wie andere darauf hingewiesen haben - das ist vollkommen legal unter den Standards.

2

Der Typ eines Stringliteral wie "Hello" ist Array von const char daher Sie lenken zwei Zeiger auf etwas, das nicht erlaubt ist, ändern zu je.

Der C++ - Standard gibt Compilern die Freiheit, identische konstante Werte miteinander zu verschmelzen (beachten Sie, dass Compiler nicht erforderlich sind zu tun).

ähnliche Werke: Die Erklärungen sind daher ungültig und muss geändert werden:

const char *str1 = "Hello"; 
const char *str2 = "Hello"; 

oder wenn Sie

char const *str1 = "Hello"; 
char const *str2 = "Hello"; 

wollen, die schön lesen, wenn von rechts nach links zu lesen:

str1 is a pointer to const char 

.

Verwandte Themen