2012-11-22 4 views
7

Quand je lance ce programme en utilisant MinGW, im obtenir la sortie comme « = »Deux littéraux de chaîne ont la même valeur de pointeur?

#include<iostream> 

using namespace std; 

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

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


return 0; 
} 

Cependant, logiquement, il devrait être! =, Coz ce sont des pointeurs et ils pointent vers différents emplacements de mémoire. Quand je cours ce code dans mon Turbo C++, j'obtiens! =

+2

Avez-vous désactivé les optimisations? –

+9

"et ils pointent vers différents emplacements de mémoire" ... eh bien, il se trouve qu'ils pointent vers le même emplacement. Ceci est autorisé –

+3

Les deux backquotes dans le code source devraient l'empêcher de compiler (et avec un compilateur C++ 11 conforme l'absence de 'const' devrait l'empêcher de compiler). –

Répondre

13

Vous avez raison en ce qu'ils sont des pointeurs. Cependant, qu'ils pointent vers des emplacements différents ou non dépend de la mise en œuvre. Il est parfaitement valable pour un compilateur de stocker une chaîne littérale juste une fois et d'utiliser son adresse partout où il est utilisé dans le code.

8

Il n'y a aucune garantie que les deux pointeurs pointent vers des emplacements de mémoire différents. Peut-être que c'est parce que les optimisations, ou le compilateur utilise ses propres règles ... le comportement est "Implémentation Définie".

Selon la norme (C++ 11 §2.14.5 littéraux de chaîne):

Que tous les littéraux de chaîne sont distincts (qui est, sont stockés dans les objets ne se chevauchent pas) est mise en œuvre définie.

0

char *str1 = "Hello"; - cette ligne, bien qu'autorisée (par de nombreux compilateurs), est une mauvaise idée à faire. Il n'est fondamentalement autorisé que pour la rétrocompatibilité avec C, et écrire dans * str1 entraîne un comportement indéfini. Je recommanderais de trouver le paramètre du compilateur qui vous donne des avertissements quand vous faites ceci, et si votre compilateur manque de tels avertissements trouvant un nouveau compilateur.

La norme C++ donne aux compilateurs et aux environnements d'exécution des niveaux de liberté ridicules autour desquels "String literals" sont stockés. Ils peuvent littéralement utiliser un pointeur vers la partie "literal" de "String literals" comme valeur de pointeur pour "literal", et les stocker en mémoire dans laquelle vous vous seriez désintégré lorsque vous tentez de les modifier n'est pas inattendu.

Notez que char buf1[] = "Hello"; fait quelque chose fondamentalement différent de celui char* str1 = "Hello";: il initialise en fait le tampon buf1 avec les caractères {'H','e','l','l','o','\0'}.

+0

La norme définit 'char * str =" Hello ";' comme non valide. Quand les compilateurs le supportent encore, c'est pour le service client, mais contre la norme. –

2

Ceci est un résultat attendu. Vous pouvez vérifier cela en regardant l'assemblage sous-jacent. Par exemple, si je construis avec:

g++ -S ptr.c 

alors vous pouvez voir ce qui suit dans la sortie de fichier (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 

J'ai commenté les deux bits clés - une seule l'apparence de 'Hello' se trouve dans la section rdata du code sous-jacent, et vous pouvez voir que str1 et str2 sont placés vers la fin, tous deux pointant vers la même étiquette: LC0. C'est beacuse 'Bonjour' est un littéral de chaîne et, surtout, est constante.

Comme d'autres l'ont souligné - cela est parfaitement légal selon les normes.

2

Le type d'une chaîne littérale comme "Hello" est tableau de const charbon, par conséquent, vous dirigez deux pointeurs vers quelque chose qui est pas autorisé à jamais changer.

La norme C++ donne aux compilateurs la liberté de fusionner des valeurs constantes identiques ensemble (notez que les compilateurs ne sont pas requis pour le faire).

connexes: Les déclarations ne sont donc pas valide et doit être modifié pour:

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

ou si vous voulez

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

qui se lit bien à la lecture de droite à gauche:

str1 is a pointer to const char 

.

Questions connexes