Que se passe-t-il réellement lorsqu’un pointeur sur un entier est converti en un pointeur sur un caractère?

int i=40; char *p; p=(char *)&i;//What actually happens here? printf("%d",*p); 

Quelle sera la sortie? S’il vous plaît aider!

 p=(char *)&i;//What actually happens here? 

Il prend l’adresse de i et la jette sur un pointeur de caractère. Donc, la valeur de *p est maintenant le premier octet de i . Quelle est cette valeur dépend de la plate-forme.

Commençons par regarder comment le contenu de i et p serait mis en mémoire (en supposant un ordre big-endian):

 Adresse d'élément 0x00 0x01 0x02 0x03
 ---- ------- ----------------------
    i 0x08000000 0x00 0x00 0x00 0x28
    p 0x08000004 0x ??  0x ??  0x ??  0x ??

Puisque p est déclaré en tant que variable automatique, il n’est initialisé à rien et contient un motif de bits aléatoire représenté par 0x?? .

Dans la ligne

 p = (char *)&i; 

l’expression &i à l’adresse de i , ou 0x08000000, et son type est un pointer to int , ou int * . La conversion convertit le type de int * en char * et le résultat est affecté à p .

Voici à quoi ressemblent les choses dans la mémoire après l’affectation:

 Adresse d'élément 0x00 0x01 0x02 0x03
 ---- ------- ----------------------
    i 0x08000000 0x00 0x00 0x00 0x28
    p 0x08000004 0x08 0x00 0x00 0x00

Donc, la valeur de p est maintenant l’ adresse de i . Dans la ligne

 printf("%d", *p); 

le type de l’expression *p est char et sa valeur est celle qui est stockée dans l’adresse 0x08000000, qui dans ce cas est 0. Comme printf est une fonction variadique, la valeur de *p est promue du type char au type int .

Donc, pour ce cas particulier, la sortie est “0”. Si l’ordre était little-endian, la carte ressemblerait à

 Adresse d'élément 0x03 0x02 0x01 0x00
 ---- ------- ----------------------
    i 0x08000000 0x00 0x00 0x00 0x28
    p 0x08000004 0x08 0x00 0x00 0x00

et la sortie serait “40”.

Notez que tout cet exemple suppose que les pointeurs de nombre entier et de caractère ont la même taille et la même présentation. cela n’est pas garanti partout (voir Online C Standard (n1256 version) , section 6.2.5, paragraphe 27), vous ne pouvez donc pas vous fier à ce que cela fonctionne comme vous le souhaitez (en supposant que j’ai raison int et char ne sont pas des types compatibles tels que définis par la norme, mais je peux me tromper à ce sujet). Dactylographier en général n’est pas sûr.

vous voilà

int i = 40; // allouer de la mémoire pour l’entier i et lui affecter la valeur 40

 char *p = (char*)&i; 

alors ici vous définissez une variable de pointeur et lui atsortingbuez l’adresse de i après l’avoir convertie en char*

supposons que i soit alloué à 1021 address donc p aura cette adresse avec la limite de 1 octet donc il devrait contenir le first 8 bit from the representation of 40;

comme 40 a été couvert sous les 8 premiers bits de 2 octets, il aura un équivalent de 40 caractères, mais comme vous l’imprimez avec %d it shopuld print 40 ;

Ça dépend. Sous Windows, la sortie sera 40, mais c’est simplement à cause de nombreuses coïncidences:

Tout d’abord, printf ne vérifie pas (ne peut pas) vérifier le type de ses arguments. Par conséquent, puisqu’il voit% d dans la chaîne de formatage, il suppose que l’argument donné est un entier. Bien que * p ne soit qu’un caractère, le résultat est promu en int (comme pour tout argument qui n’est pas spécifié dans le prototype de fonction).

Deuxièmement, p désignera la mémoire prise par la variable i, mais comme il s’agit d’un pointeur de caractère, il ne prendra qu’un octet dans la mémoire de i. Puisque Windows / Intel utilise la première convention de premier octet, 40 sera stocké sous la forme d’octet “40 0 0 0”. Ainsi, puisque * p prend le premier octet (caractère), le résultat sera 40. Si j’aurais le Si la valeur est égale ou supérieure à 256, le résultat serait incorrect.

Que se passe-t-il lorsque int pointer est converti en caractère? Il y a une autre question marquée comme dupliquée ici, j’essaie de l’expliquer.

 $ cat ac #include  int main(){ int a; char *x; x = (char *) &a; a=512; x[0]=1; x[1]=2; printf("%d\n",a); return 0; } 

Comstackr et exécuter:

 $ gcc ac && ./a.out 513 

Pourquoi c’est 513? Nous pouvons utiliser gdb pour voir la cause première.

 $ gcc ac -g && gdb ./a.out (gdb) list 1 #include  2 3 int main(){ 4 int a; 5 char *x; 6 x = (char *) &a; 7 a=512; 8 x[0]=1; 9 x[1]=2; 10 printf("%d\n",a); 

définissez un sharepoint rupture à la ligne 8 du courant alternatif et exécutez

 (gdb) b ac:8 Breakpoint 1 at 0x40113d: file ac, line 8. (gdb) run 

une fois le programme arrêté au point d’arrêt, affiche l’adresse de mémoire de la variable a.

 (gdb) p &a $2 = (int *) 0x7fffffffd9d4 (gdb) px $3 = 0x7fffffffd9d4 "" 

L’adresse mémoire de la variable a est 0x7fffffffd9d4 et la valeur de la variable x est la même.

avant de montrer le contenu de la mémoire, comprenons comment 512 au format hexadécimal,

 00 00 02 00 

et x86 est little endian, donc en mémoire cela devrait être:

 [higher address] 00 02 00 00 [lower address] 

Montrons la vraie mémoire, exactement comme nous le pensions.

 (gdb) x/4xb 0x7fffffffd9d4 0x7fffffffd9d4: 0x00 0x02 0x00 0x00 

puis, affichez l’adresse mémoire de x [0] et x [1], et convertissez le contenu de la mémoire en valeur réelle, il ne devrait pas être difficile de comprendre pourquoi imprimer 513

 (gdb) p &x[0] $4 = 0x7fffffffd9d4 "" (gdb) p &x[1] $5 = 0x7fffffffd9d5 "\002"