#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?
#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?
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.
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.
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.
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.)
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 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.