80 votes

Les adresses de deux pointeurs sont mêmes

#include<stdio.h>
#include<string.h>

int main()
{
  char * p = "abc";
  char * p1 = "abc";
  printf("%d %d", p, p1);
}

Lorsque j'imprime les valeurs des deux pointeurs, c'est l'impression de la même adresse. Pourquoi?

87voto

KingsIndian Points 26855

Si les deux littéraux de chaîne avec le même contenu est placé dans le même emplacement de mémoire ou différents emplacements de mémoire est dépendant de l'implémentation.

Vous devez toujours traiter p et p1 sous forme de deux pointeurs (même si elles ont le même contenu) qu'ils peuvent ou ne peuvent pas point à la même adresse. Vous ne devriez pas compter sur les optimisations du compilateur.

C11 Standard, 6.4.5, les littéraux de Chaîne, sematics

Il n'est pas précisé si ces tableaux sont distinctes, à condition que leur les éléments ont les valeurs appropriées. Si le programme tente de modifier un tableau, le comportement est indéfini.

28voto

alk Points 26509

Votre compilateur semble être assez intelligent, détectant à la fois les littéraux sont les mêmes. Et comme les littéraux sont constants, le compilateur a décidé de ne pas les stocker deux fois.

Il semble important de mentionner que ce n'est pas nécessairement besoin d'être le cas. Veuillez voir le Blue Moon's réponse sur ce.


Btw: L' printf() déclaration devrait ressembler à ceci

printf("%p %p", (void *) p, (void *) p1);

en tant que "%p" doit être utilisée pour imprimer les valeurs de pointeur, et il est défini pour un pointeur de type void * seulement.*1


Aussi, je dirais que le code manque une return déclaration, mais le C standard semble être en cours de modification. D'autres pourraient bien vouloir clarifier cela.


*1: la conversion en void * ici n'est pas nécessaire pour char * des pointeurs, mais pour des pointeurs vers tous les autres types.

18voto

kfsone Points 7375

Votre compilateur a fait quelque chose appelé "chaîne de mise en commun". Vous avez spécifié que vous vouliez deux pointeurs, les deux pointant vers la même chaîne de caractères littérale - il seulement fait une copie de la traduction littérale.

Techniquement: Il faudrait se sont plaints à vous pour ne pas faire les pointeurs "const"

const char* p = "abc";

C'est probablement parce que vous êtes à l'aide de Visual Studio ou vous utilisez GCC sans -Mur.

Si vous avez expressément voulez être enregistrées deux fois dans la mémoire, essayez de:

char s1[] = "abc";
char s2[] = "abc";

Ici, vous déclarez explicitement que vous voulez de deux c-string des tableaux de caractères plutôt que deux pointeurs de caractères.

Mise en garde: la Chaîne de la mise en commun est un compilateur/optimiseur de fonction et non pas une facette de la langue. Comme ces différents compilateurs sous différents environnements va produire un comportement différent selon les choses comme le niveau d'optimisation, les drapeaux de compilation et si les chaînes sont dans les différentes unités de compilation.

15voto

dbaupp Points 20762

Comme d'autres l'ont dit, le compilateur est de remarquer qu'ils ont la même valeur, et donc de décider de partager des données dans l'exécutable final. Mais il devient de plus sophistiqué: quand je compile le suivant, gcc -O

#include<stdio.h>
#include<string.h>

int main()
{
  char * p = "abcdef";
  char * p1 = "def";
  printf("%d %d", p, p1);
}

il imprime 4195780 4195783 pour moi. C'est, p1 commence 3 octets après l' p, de sorte que GCC a vu le suffixe commun d' def (y compris l' \0 terminator) et fait un similaire optimisation de celui que vous avez indiqué.

(C'est une réponse parce que c'est trop long pour être un commentaire.)

3voto

Salgar Points 4803

Les littéraux de chaîne dans le code sont stockées dans une lecture seule segment de données du code. Lorsque vous écrivez un littéral de chaîne comme "abc", il retourne en fait un "const char*" et si vous aviez tous les avertissements du compilateur sur il vous dira que vous lancez un sort à ce point. Vous n'êtes pas autorisés à modifier ces chaînes pour la raison, vous l'avez souligné à cette question.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X