Due valori letterali stringa hanno lo stesso valore puntatore?

Quando eseguo questo programma usando MinGW, sto ricevendo l’output come “=”

#include using namespace std; int main() { char *str1 = "Hello"; char *str2 = "Hello"; if(str1==str2) cout<<"="; else cout<<"!="; return 0; } 

Tuttavia, logicamente, dovrebbe essere! =, Perché questi sono puntatori e indicano punti di memoria diversi. Quando eseguo questo codice nel mio Turbo C ++, ottengo! =

Hai ragione, sono indicatori. 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.

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 String Literals):

Se tutte le stringhe letterali sono distinte (ovvero vengono memorizzate in oggetti non sovrapposti) viene definita l’implementazione.

Questo è un risultato previsto. È ansible verificare ciò osservando l’assembly sottostante. Ad esempio, se costruisco con:

 g++ -S ptr.c 

quindi puoi vedere quanto segue nell’output del file (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 i due bit chiave: solo una parte 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 è falso ‘Ciao’ è una stringa letterale e, soprattutto, è costante .

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

Il tipo di una stringa letterale come "Hello" è una matrice di const char , quindi, stai indirizzando due puntatori a qualcosa che non è consentito modificare.

Lo standard C ++ offre ai compilatori la libertà di unire valori costanti identici insieme (si noti che i compilatori non sono tenuti a farlo).

Correlati: le dichiarazioni non sono valide e devono essere modificate in:

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

o se vuoi

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

che legge bene quando legge da destra a sinistra:

 str1 is a pointer to const char 

.

char *str1 = "Hello"; – questa linea, mentre è consentita (da molti compilatori), è una ctriggers idea di fatto. 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à riguardo a dove sono memorizzati "String literals" . Potrebbero letteralmente usare un puntatore alla parte "literal" di "String literals" come valore del puntatore per "literal" e archiviarli in memoria in cui avresti segfault quando tenti di modificarli non è inaspettato.

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