2012-11-22 13 views
7

Quando ho eseguito questo programma usando MinGW, im ottenendo uscita come "="Due valori letterali stringa hanno lo stesso valore puntatore?

#include<iostream> 

using namespace std; 

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

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


return 0; 
} 

Tuttavia, logicamente, dovrebbe essere! =, Coz questi sono puntatori e sono rivolte a diverse locazioni di memoria. Quando eseguo questo codice nel mio Turbo C++, ottengo! =

+2

Hai disattivato le ottimizzazioni? –

+9

"e stanno puntando a diverse posizioni di memoria" ... beh, risulta che in realtà stanno puntando alla stessa posizione. Questo è permesso. –

+3

Le due backquote nel codice sorgente dovrebbero impedirne la compilazione (e con un compilatore C++ 11 conforme, la mancanza di 'const' dovrebbe impedirne la compilazione). –

risposta

13

Hai ragione nel senso che sono puntatori. Tuttavia, se puntano a posizioni diverse o meno dipende dall'implementazione. È perfettamente valido per un compilatore memorizzare una stringa letterale una volta sola e usare il suo indirizzo ovunque sia usato nel codice.

8

Non ci sono garanzie che i due puntatori puntino a posizioni di memoria differenti. Forse è perché le ottimizzazioni o il compilatore usa le proprie regole ... il comportamento è "Implementazione definita".

Secondo lo standard (C++ 11 §2.14.5 letterali di stringa):

Se tutte le stringhe letterali sono distinte (cioè, sono memorizzati in oggetti sovrapposti) viene attuazione definita.

0

char *str1 = "Hello"; - questa linea, mentre consentito (da molti compilatori), è una cattiva idea di fare in realtà. Fondamentalmente è permesso solo per la compatibilità con C, e in realtà scrivere a * str1 comporta un comportamento indefinito. Ti consiglio di trovare l'impostazione del compilatore che ti dà avvertimenti quando lo fai, e se il tuo compilatore manca di tali avvertimenti per trovare un nuovo compilatore.

Lo standard C++ offre ai compilatori e agli ambienti di esecuzione ridicole quantità di libertà su dove sono memorizzati "String literals". Potrebbero letteralmente usare un puntatore alla parte "literal" di "String literals" come valore di puntatore per "literal" e archiviarli in memoria in cui si farebbe segfault quando si tenta di modificarli non inaspettato.

Nota che char buf1[] = "Hello"; fa qualcosa di fondamentalmente diverso rispetto char* str1 = "Hello";: in realtà inizializza il buffer buf1 con i personaggi {'H','e','l','l','o','\0'}.

+0

Lo standard definisce 'char * str =" Hello ";' come non valido. Quando i compilatori lo supportano ancora, è per la cura del cliente, ma contro lo standard. –

2

Questo è un risultato previsto. È possibile verificare ciò osservando l'assembly sottostante. Per esempio, se io costruisco con:

g++ -S ptr.c 

allora si può vedere quanto segue nel file di output (ptr.s):

 .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 

Ho commentato le due bit della chiave - una sola l'aspetto di "Ciao" si trova nella sezione rdata del codice sottostante, e puoi vedere che str1 e str2 sono impostati verso la fine, entrambi puntati alla stessa etichetta: LC0. Questo è perché "Hello" è una stringa letterale e, soprattutto, è costante.

Come altri hanno sottolineato, questo è perfettamente legale secondo gli standard.

2

Il tipo di una stringa letterale come "Hello" è gamma di const char, di conseguenza, si stanno dirigendo due puntatori a qualcosa che non è consentito cambiare mai.

Lo standard C++ offre ai compilatori la libertà di unire valori costanti identici insieme (notare che i compilatori non sono necessari per farlo).

correlati: Le dichiarazioni sono quindi validi e deve essere modificato per:

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

o se si desidera

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

che legge bene durante la lettura da destra a sinistra:

str1 is a pointer to const char 

.

Problemi correlati