2011-03-08 5 views
1

J'ai construit les sections de code ci-dessous pour me aider à comprendre le pointeur déréférencement et transtypage en C.déréférencement et transtypage

char a = 'a'; 
char * b = &a; 
int i = (int) *b; 

Pour ce qui précède, je comprends que sur la 3ème ligne, j'ai déréférencé b et a obtenu 'a' et (int) transcrira la valeur de 'a' à sa valeur correspondante de 97 qui est stockée dans i. Mais pour cette section de code:

char a = 'a'; 
char * b = &a; 
int i = *(int *)b; 

Il en résulte i étant un certain grand nombre arbitraire comme 792351. Je suppose que c'est une adresse mémoire, mais ma question est pourquoi? Lorsque je transpose b en un pointeur entier, est-ce que b fait pointer vers une autre zone en mémoire? Que se passe-t-il?

EDIT: Si cette procédure ne fonctionne pas, alors pourquoi quelque chose comme ce travail:

char a = 'a'; 
void * b = &a; 
char c = *(char *)b; 

Cette correctement attribue 'a' à c.

Répondre

3

Votre int est plus grand que votre char - vous obtenez la valeur 'a' + des données aléatoires suivantes en mémoire.

par exemple, en supposant cette mise en page en mémoire:

'a' 
0xFF 
0xFF 
0xFF 

Votre char * et int * les deux vers le 'a'. Lorsque vous déréférencez le char *, vous obtenez uniquement le premier octet, le 'a'. Lorsque vous déréférencer le int * (en supposant que votre int est 32 bits), vous obtenez le 'a' et les 3 octets de données non initialisées le suivant.

EDIT: En réponse à la question mise à jour:

En char c = *(char *)b;, b pointe encore à la valeur 'a'. Vous lancez à un char *, puis déréférencer, obtenir le omble pointé par un char *

+0

merci qui a beaucoup de sens. – Sam

1

Vous jetant un pointeur char à un pointeur int. Les caractères sont (habituellement) stockés en tant que 8 bits. int s, d'autre part, sont 32 bits (ou 64 sur les systèmes 64 bits). Donc, si vous regardez les 24 autres bits de la mémoire à côté de la valeur 8 bits de b, vous obtiendrez un tas de bits supplémentaires qui n'ont pas été initialisés. Même la position de *b dans i dépend de l'architecture.

big-endian: **** ****|**** ****|**** ****|0110 0001 
little-endian: 0110 0001|**** ****|**** ****|**** **** 

Lorsque vous lancez le caractère stocké dans ce qui précède, tous les astérisques deviennent pertinents.

0

Lorsque vous tapez le cast vers un type (int *), il se référera à un total de 4 octets (taille si int) en mémoire.

1

Depuis un char est 1 octet long, et un int 4, lorsque vous lisez un int à l'adresse d'un seul caractère, vous lisez le caractère et 3 autres octets.Le contenu de ces octets est juste ce qu'il se passe en mémoire (pointeurs, la valeur de b) et pourrait même être non alloué (ce qui entraîne une erreur de segmentation ).

2

La dernière ligne qui vous préoccupe fait une très mauvaise chose. Premièrement, il traite b comme int* alors que b est un char*. C'est-à-dire que le pointeur de mémoire de b est supposé de 4 octets (typiquement) au lieu de 1 octet. Donc, quand vous le dérérez, il va au 1 octet pointé par le b réel, prend aussi les 3 octets suivants, traite ces 4 octets comme un seul int, et vous donne le résultat. Voilà pourquoi c'est la poubelle.

En général, la conversion d'un type de pointeur en un autre type de pointeur doit être effectuée avec une grande prudence.

0

Dans le second cas, vous traitez la même adresse comme si elle indiquait un int. Officiellement, le résultat est simplement un comportement indéfini.

De manière réaliste, ce qui se passe est que tout ce qui se passe dans les quatre octets commençant à cette adresse est interprété comme un int. 4 octets supposant un int de 32 bits - si votre implémentation a, par exemple, un int de 64 bits, ce sera 8 octets.