160 votes

Si vous pensez que vous savez des pointeurs ?

J'ai été montré récemment, et a pensé que c'était vraiment un super morceau de code. Supposons une architecture 32 bits.

#include <stdio.h>

int main(void) {
 int x[4];
 printf("%p\n", (void*) (x));
 printf("%p\n", (void*) (x + 1));
 printf("%p\n", (void*) (&x));
 printf("%p\n", (void*) (&x + 1));
}

Sans compiler le programme, en quoi est-il de la sortie, et pourquoi? Si vous pensez qu'une certaine sortie sera arbitraire, de dire, d'inventer une valeur, et prétendre que c'était de la valeur de sortie.

Edit: Donc, la question a été répondu, le plus rapide coup de feu à wnoise! Cependant, j'encourage les gens qui sont juste de la lecture de ce défi d'essayer de le faire vous-même, avant de vérifier les réponses.

Edit 2: Converti les pointeurs de type void*, comme par Chris Young. Je crois que la plupart des compilateurs de traiter les deux de la même façon, mais il faut être correct.

170voto

Edward Z. Yang Points 13760

Bien! Nous avons eu quelques bonnes réponses, et certains correct explications. Mais nous allons en dire un peu plus sur ce qu'il se passe:

int main(void) {
 int x[4];
 printf("%p\n", x); // 0x100
 printf("%p\n", x + 1); // 0x104
 printf("%p\n", &x); // 0x100
 printf("%p\n", &x + 1); // 0x110
}

Première ligne:

 printf("%p\n", x); // 0x100

De base de la récupération de l'adresse du pointeur. C'est la seule valeur arbitraire de quatre.

 printf("%p\n", x + 1); // 0x104

De base de l'arithmétique des pointeurs. Rappelons que la taille de l' int sur un système 32 bits, soit 4 octets, de sorte que l'adresse multiplié par quatre. C'est maintenant l'indice 1 du tableau d'entiers.

 printf("%p\n", &x); // 0x100

Si on vous a appris que les matrices sont équivalentes à des pointeurs, cela va vous confondre: la réponse la plus courante est que c'est une autre valeur arbitraire, c'est à dire le pointeur vers le pointeur, résidant quelque part sur la pile. Si vous essayez de code qui tente de le faire, cependant, votre compilateur va se plaindre (GCC dit "erreur: le label" x "utilisé mais non défini").

La bonne réponse est que x est l'adresse pour le premier entier de la matrice; et x est maintenant une adresse pour le tableau réel, qui se trouve être la même que l'adresse pour le premier entier de la matrice.

Si x a été définie comme x*, et nous malloc ed le montant approprié de la mémoire, le comportement serait différent. Et lors du passage de pointeurs par le biais de fonctions, la distinction disparaît. Mais un pointeur vers le tableau n'est pas la même chose qu'un pointeur vers le premier élément du tableau!

 printf("%p\n", &x + 1); // 0x110

Si vous avez répondu 3 mal, vous auriez certainement obtenir 4 faux, parce que l'extension de cette ligne de pensée, nous sommes en train de parler d'un pointeur vers un pointeur, et puis l'arithmétique des pointeurs, de 4 octets de la valeur.

Si vous avez réalisé que 3 est maintenant un pointeur sur un tableau, vous aussi, vous rendre compte que faire de l'arithmétique des pointeurs serait en ce qui concerne la taille du tableau, pas le pointeur.

Merci à tous ceux qui ont participé!

110voto

Chris Young Points 8525

La sortie est un comportement indéfini, car %p exige que le pointeur être jeté à l' void * depuis les autres types de pointeur peut ne pas avoir la même taille et de la représentation en void *. En supposant qu'une partie du programme est corrigé, la sortie serait définie par l'implémentation. Le résultat serait une mise en œuvre définies représentation des valeurs suivantes, en supposant n = la valeur du pointeur de l'adresse du premier élément du tableau:

n
n + sizeof(int)
n 
n + 4 * sizeof(int)

La raison pour les 3 premières lignes devraient être évidentes. La raison pour la dernière ligne est parce qu' &x est de type int(*)[4] et pas int *.

22voto

wnoise Points 6448
0x12345678
0x1234567C
0x12345678
0x12345688

10voto

zvrba Points 14028

Techniquement, il y a deux « bonnes » réponses parce que même sur une architecture 32 bits, int doit être de 16 bits.

0voto

Newtopian Points 3335

wow... ça fait un loooong moment depuis le bon vieux jours ...

mais... encore.

x et x sont fondamentalement la même chose ici ne sont-ils pas, les tableaux en C sont juste sucre syntaxique sur l'arithmétique des pointeurs, donc j'imagine que, fondamentalement, deux fois la même paire de lignes à la sortie du programme ci-dessus... à moins que l'adresse d'une adresse rendements encore une autre adresse...

ho... la douleur.. mon cerveau fait mal... besoin de plus de bière


weeeel vous le regardez, ils sont tous les deux adresses, mais l'arithmétique des pointeurs seront affectés différemment par l'opérateur & ... en tapant le pointeur différemment

x est l'adresse du premier élément (tapé int)
et x est l'adresse du tableau de int (tapé int[4])

bien, merci

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