2012-05-24 20 views
5

Così ho fatto il seguente test:Caratteri letterali stringa che contengono ' 0' - perché non sono gli stessi?

char* a = "test"; 
char* b = "test"; 
char* c = "test\0"; 

E ora la domanda:

1) E 'garantito che a==b? So che sto confrontando gli indirizzi. Questo non è pensato per confrontare le stringhe, ma se letterali stringa identici sono memorizzati in una singola posizione di memoria

2) Perché non a==c? Il compilatore non dovrebbe essere in grado di vedere che si riferiscono alla stessa stringa?

3) È un ulteriore \0 aggiunto alla fine di c, anche se ne contiene già uno?

Non volevo chiedere a 3 domande diverse per questo perché sembrano in qualche modo correlati, mi dispiace per quello.

Nota: il tag è corretto, sono interessato al C++. (anche se si prega di specificare se il comportamento è diverso per C)

+7

Dovrebbe essere 'char const * a = ...'. –

+0

aeb hanno lo stesso valore, ma ciò non significa necessariamente che siano la stringa _same_. –

+0

@HunterMcMillen - in realtà è esattamente ciò che vorrebbe dire. –

risposta

18

È garantito che a == b?

No. Ma è consentito dalla §2.14.5/12:

Se tutte le stringhe letterali sono distinte (cioè, vengono memorizzate in oggetti sovrapposti) è definito dall'implementazione. L'effetto del tentativo di modificare una stringa letterale non è definito.

E come si può vedere da questa ultima frase usando char* invece di char const* è una ricetta di guai (e il vostro compilatore dovrebbe essere di rigetto; assicuratevi di avere avvertimenti abilitati e livelli elevati di conformità selezionati).

Perché non a == c? Il compilatore non dovrebbe essere in grado di vedere che si riferiscono alla stessa stringa?

No, non è necessario che si riferiscano allo stesso array di caratteri. Uno ha cinque elementi, gli altri sei. Un'implementazione potrebbe memorizzare i due in memoria sovrapposta, ma non è necessario.

È un \ 0 aggiunto alla fine di c, anche se ne contiene già uno?

Sì.

+0

Potrebbe anche valere la pena di spiegare che '" test "' è un 'char const [5]' nel contesto del motivo per cui A & B * potrebbe * sovrapporsi ma C no. – AJG85

+0

Grazie. Un'altra domanda. Se uso 'strcmp' per confrontare' a' e 'c', dirà che sono uguali? Inoltre, è consentito per 'a == c'? – AMCoder

+0

@ AJG85 perché non 'c' si sovrappone? Lo standard lo consente esplicitamente (la citazione è nella risposta e non limita a letterali identici) e un programma non può dire la differenza senza invocare un comportamento indefinito. –

6

1 - assolutamente no. a potrebbe == b se il compilatore sceglie di condividere la stessa stringa statica.

2 - perché non si riferiscono alla stessa stringa

3 - sì.

Il comportamento non è diverso tra C e C++ eccetto che i compilatori C++ devono rifiutare l'assegnazione a non-const char *.

+0

La conversione da stringa letterale a 'char *' è deprecata, ma non proibita in C++. –

+0

@james è vietato in C++ 11 –

+0

@ JohannesSchaub-litb: Assolutamente no! Questa è la migliore notizia che ho sentito tutto il giorno. g ++ 4.7, clang 3.1 e VC11 accettano tutti la conversione, ma non vedo l'ora che non lo faccia :-) –

2

Il problema qui è che stai mescolando i concetti di puntatore ed equivalenza testuale.

Quando dici a == b o a == c stai chiedendo se i puntatori coinvolti puntano allo stesso indirizzo fisico. Il test non ha nulla a che fare con il contenuto testuale dei puntatori.

Per ottenere testuale di equivalenza si dovrebbe usare strcmp

+0

Si noti che 'strcmp' si fermerà al * primo * zero, quindi le stringhe' a' e 'c' saranno uguali anche se una è più lunga dell'altra. –

+0

@MarkRansom ha una lunghezza equivalente in senso testuale, ma è ciò che considererà lo strcmp. Forse dovrei espandere la mia risposta nei 3 regni che possono essere importanti qui: l'equivalenza del puntatore, l'equivalenza testuale e l'equivalenza della memoria – JaredPar

+0

-1 scusate ma ho un confronto tra puntatori lì perché voglio confrontare i puntatori. Ecco di cosa si tratta. – AMCoder

4

1) E 'garantito che a == b?

Non lo è. Nota che stai confrontando gli indirizzi e potrebbero puntare a posizioni diverse. La maggior parte dei compilatori intelligenti piegherebbe questa costante letterale duplicata, quindi i puntatori potrebbero essere uguali, ma di nuovo non è garantito dallo standard.

2) Perché non a == c? Il compilatore non dovrebbe essere in grado di vedere che si riferiscono alla stessa stringa?

Si sta tentando di confrontare i puntatori, che indicano diverse posizioni di memoria. Anche se stai confrontando il contenuto di tali indicatori, sono ancora disuguali (vedi la prossima domanda).

3) è un extra \ 0 aggiunto alla fine del c, anche se contiene già uno?

Sì, c'è.

+0

So che sto confrontando gli indirizzi, ergo la domanda. Per cancellare la domanda - ci sono letterali stringa identici situati nella stessa memoria? – AMCoder

+0

Immagino che i puntatori per 'a' e' c' possano essere uguali. Un programma non può dire la differenza senza invocare UB. –

+0

@R. Martinho Fernandes: Questo è un buon punto, credo che tu abbia ragione. –

0

Se si eseguono confronti tra puntatori di a! = B, b! = C e c! = A. A meno che il compilatore non sia abbastanza intelligente da notare che le prime due stringhe sono le stesse.

Se si esegue uno strcmp (str, str), tutte le stringhe torneranno come corrispondenze.

Non sono sicuro che il compilatore aggiungerà una terminazione null addizionale a c, ma suppongo che lo farebbe.

3

Prima nota che questo dovrebbe essere const char * in quanto è ciò che decadono i letterali delle stringhe.

  1. Entrambi creare array inizializzate con 't' 'e' 's' 't' folowed da un '\ 0' (lunghezza = 5). Il confronto per l'uguaglianza ti dirà solo se entrambi iniziano con lo stesso puntatore, non se hanno lo stesso contenuto (sebbene logicamente, le due idee si susseguono l'un l'altra).
  2. A non è uguale a C perché si applicano le stesse regole, a = 't' 'e' 's' 't' '\ 0' e b = 't' 'e' 's' 't' ' \ 0 '' \ 0 '
  3. Sì, il compilatore lo fa sempre e non dovresti farlo in modo esplicito se stai creando una stringa come questa. Se hai comunque creato un array e lo hai compilato manualmente, devi assicurarti di aggiungere il valore \ 0.

Si noti che per il mio # 3, const char [] = "Ciao Mondo" sarebbe anche ottenere automaticamente il \ 0, alla fine, mi è stato refferring a riempire manualmente la matrice, non avendo il lavoro del compilatore fuori.

+0

Non penso che 'a' e' c' siano garantiti ineguali. Lo standard consente all'implementazione di archiviare i letterali nella memoria sovrapposta e i programmi non possono dire la differenza senza invocare UB. –

+0

In realtà sono d'accordo con te che hai controllato, era un punto interessante che non avevo sentito. Il mio punto sarebbe comunque che il compilatore posizionerebbe sicuramente due terminatori nulli nel caso 2, sebbene ciò renda le operazioni non uguali, anche se la lettura delle stringhe e il controllo dei loro puntatori sarebbero uguali. Inoltre, se hai registrato la lunghezza della stringa che hai creato per c, puoi tranquillamente leggere oltre lo strlen() per 1 e non puoi per un (a meno che non si trovino nella stessa posizione che hai detto, ma non lo faresti essere in grado di garantirlo). –

+0

* Anche se il compilatore li ha memorizzati nella stessa posizione *, 'a [5]' (che tenta di leggere il valore nella stessa posizione di 'c [5]') invocherà un comportamento indefinito, perché 'a' punta a una serie di dimensioni 5. Non importa che ci sia un altro array in giro nello stesso posto. –

0

Come è stato detto poche volte in altre risposte, si stanno confrontando i puntatori.Tuttavia, vorrei aggiungere che strcmp(b,c) dovrebbe essere vero, perché smette di controllare il primo \0.

Problemi correlati