2010-01-09 8 views
0

Le code utilisémanipulation de pointeur struct

#include<stdio.h> 

struct st 
{ 
char a; 
short c; 
int b; 
}; 

struct st s1; 
int main() 
{ 
     printf("%p %p \n",(&s1.b)-1, &s1); 
} 

Si j'imprime l'adresse de &s1.b il imprime 0x804a01c et &s1.b-2 imprime 0x804a018 pourquoi il est l'impression même adresse 0x804a01c si je sélectionne &s1.b-1?

+0

Le remplissage de structure est défini par l'implémentation. –

+5

@Prasoon: cela n'a rien à voir avec le remplissage de la structure: '& s1.b' est un' int * ', et le remplissage de la structure n'a aucun effet sur le fonctionnement de l'arithmétique du pointeur avec un' int * '. –

+0

@Steve Jessop: Exactement. Plus un sur votre commentaire. – jason

Répondre

0

Merci de poster votre code. Maintenant, je vois le problème. C'est à cause du rembourrage.À savoir:

printf("sizeof(char): %d\n", sizeof(char)); 
printf("sizeof(short): %d\n", sizeof(short)); 
printf("sizeof(int): %d\n", sizeof(int)); 
printf("sizeof(struct st): %d\n", sizeof(struct st)); 

Sur ma machine, cette imprimante

1 
2 
4 
8 

Vous pourriez penser, ne devrait pas être sizeof(struct st)1 + 2 + 4 = 7? C'est certainement une pensée raisonnable, mais à cause de alignment issues il y a padding entre a et c. Par conséquent, en mémoire, le struct ressemble à la suivante (par rapport au premier octet du struct):

0x00000000: char     a 
0x00000001: padding 
0x00000002: first byte of short c 
0x00000003: second byte of short c 
0x00000004: first byte of int b 
0x00000005: second byte of int b 
0x00000006: third byte of int b 
0x00000007: fourth byte of int b 

En conséquence (par rapport à &s1):

&s1.b - 1 is ((long)&s1.b) - sizeof(int) = 4 - 4 = 0 = &s1 

C'est pourquoi les deux &s1 et &s1.b - 1 imprimera la même adresse. En particulier, si

&s1 = 0x804a01c 

puis

&s1.b = 0x804a01c + 0x00000004 = 0x804a020 

et

&s1.b - 1 = 0x804a020 - 0x00000004 = 0x804a01c 

et

&s1.b - 2 = 0x804a020 - 0x00000008 = 0x804a018 

Notez enfin que ce comportement est spécifique à la mise en œuvre. Ce n'est pas portable!

7

Il y a probablement quelque chose de mal avec votre code d'impression.

#include <stdio.h> 

struct st 
{ 
char a; 
short c; 
int b; 
}; 

struct st s1; 

int main() { 
    printf("%p\n", (void*)(&s1.b)); 
    printf("%p\n", (void*)(&s1.b - 1)); 
    printf("%p\n", (void*)(&s1.b - 2)); 
} 

Sortie:

0x403024 
0x403020 
0x40301c 
+0

right: -1 ou -2 fois sizeof (int) – stacker

+0

déclarer la structure s1 comme globale –

+2

@C Learner: déclarer 's1' comme global ne changera pas le comportement (l'arithmétique du pointeur est définie très clairement et il n'y a aucune partie du spécification qui permet l'intervention de détails spécifiques à l'implémentation ici). – jason

1

Si l'adresse de s1.b est 0x804a01c, puis & s1.b-2 doit être 0x804a014 (en supposant que int est de 4 octets), non 0x804a018. Peut-être que vous avez fait une erreur lorsque vous avez signalé l'adresse?

+0

Vous voulez dire 4 octets, pas 32 bits :-). 4 octets == 32 bit ssi 'CHAR_BIT == 8'. –

+0

Bien sûr. Merci pour la correction. – kusma

2

Très probablement vous imprimez mal:

#include <stdio.h> 

struct st 
{ 
    char a; 
    short c; 
    int b; 
}; 
struct st s; 

int main(void) 
{ 
    printf("s: %p\n", (void *)&s); 
    printf("s.a: %p\n", (void *)&s.a); 
    printf("s.b: %p\n", (void *)&s.b); 
    printf("s.b-1: %p\n", (void *)(&s.b-1)); 
    printf("s.b-2: %p\n", (void *)(&s.b-2)); 
    return 0; 
} 

Prints pour moi:

s: 0x100001068 
s.a: 0x100001068 
s.b: 0x10000106c 
s.b-1: 0x100001068 
s.b-2: 0x100001064 

choses à noter:

  • pointeur sur struct == pointeur sur struct de premier élément (garantie par la norme C),
  • Je suis l'impression de la pointeurs avec "%p" chaîne de format. "%p" a besoin de void *, et puisque printf est une fonction variadique, j'ai besoin de transformer les arguments en printf en void * dans ce cas.

Qu'est-ce que le programme ci-dessus pour vous imprimer?

Modifier: basé sur le code réel affiché pour l'impression que vous avez publié plus tard: vous ne recevez pas la même valeur pour &s1.b et &s1.b-1. Vous obtenez la même valeur pour &s1.b-1 et &s1. La réponse à cette question est: cela se produit à cause du hasard. Dans votre cas, il y a un rembourrage struct et sizeof(short)+sizeof(char) se trouve être ≤ sizeof(int). Si vous étiez sur une machine où l'une de ces hypothèses était invalide, vous ne verriez pas ce comportement. Je suis sûr que si vous avez changé char ou short à int dans votre code, &s1.b-1 serait pas égal &s1, une fois imprimé.

Enfin, vous devriez jeter des pointeurs vers void * avant d'imprimer:

printf("%p %p \n",(void *)((&s1.b)-1), (void *)&s1);