2011-06-24 2 views
12

Étant donné que le nom d'un tableau est en fait un pointeur vers le premier élément d'un tableau, le code suivant:Différence entre le pointeur sur le pointeur et le pointeur sur le tableau?

#include <stdio.h> 

int main(void) 
{ 
    int a[3] = {0, 1, 2}; 
    int *p; 

    p = a; 

    printf("%d\n", p[1]); 

    return 0; 
} 

impressions 1, comme prévu.

Maintenant, étant donné que je peux créer un pointeur qui pointe vers un pointeur, j'écrit ce qui suit:

#include <stdio.h>                

int main(void)                 
{                    
     int *p0;                 
     int **p1;                
     int (*p2)[3];               
     int a[3] = {0, 1, 2};             

     p0 = a;                 
     p1 = &a;                 
     p2 = &a;                 

     printf("p0[1] = %d\n(*p1)[1] = %d\n(*p2)[1] = %d\n",      
         p0[1], (*p1)[1], (*p2)[1]);        

     return 0;                
} 

Je m'y attendais compiler et imprimer

p0[1] = 1 
(*p1)[1] = 1 
(*p2)[1] = 1 

Mais au contraire, il va mal à la compilation, en disant:

test.c: In function ‘main’: 
test.c:11:5: warning: assignment from incompatible pointer type [enabled by default] 

Pourquoi cette affectation est-elle erronée? Si p1 est un pointeur vers un pointeur sur un int et a est un pointeur vers un int (parce que c'est le nom d'un tableau de int s), pourquoi ne puis-je attribuer &a-p1?

+1

Il ya quelque temps, j'ai écrit [une réponse à une question similaire] (http://stackoverflow.com/questions/5181237/confusion-in-data-types-in-a-2d-array) que vous pourriez aimer. – pmg

+0

Merci pour l'indice! – jpmelos

Répondre

16

Ligne 11 est

 p1 = &a; 

p1 est de type int ** et a est de type int[3], non?

Puits; &a est de type int(*)[3] et ce type n'est pas compatible avec le compilateur int** comme vous a dit

Vous pouvez essayer

 p1 = &p0; 

Et lire the c-faq, en particulier l'article 6.

En bref: tableaux ne sont pas des pointeurs, et les pointeurs ne sont pas des tableaux.

+1

Ce genre de subvertit tout ce que je pensais savoir sur les tableaux et les pointeurs. Je me demande comment je me suis débrouillé avec ça pendant tant d'années, vraiment. Merci de le préciser. – jpmelos

+1

@jpmelos - La façon dont les tableaux et les pointeurs fonctionnent est étonnamment subtile, et pas très facile à comprendre dès le début de l'apprentissage. –

+1

Vous vous en êtes tiré parce que très souvent les tableaux se comportent comme des pointeurs et des pointeurs se comportent comme des tableaux ... ** mais ils ne sont pas les mêmes! ** Lire [la c-faq] (http://c-faq.com /) section 6: c'est vraiment intéressant :) – pmg

0

Pour de nombreuses opérations, a implique &a et les deux retournent la même chose: L'adresse du premier élément dans le tableau.

Vous ne pouvez pas obtenir l'adresse du pointeur car la variable ne stocke pas le pointeur. a n'est pas un pointeur, même s'il se comporte comme un dans certains cas.

+0

Alors pourquoi 'p2 = & a' fonctionne et' p1 = & a' non? – jpmelos

+2

@jpmelos - Parce que le type '& a' est' int (*) [3] 'plutôt que' int ** '. –

+4

Non! 'a' n'implique pas' & a' pour beaucoup de choses. Cela implique '& a [0]'! – nos

6

a n'est pas un pointeur sur int, il désintègre pour tels dans certaines situations. Si &a était de type int **, vous ne pourriez pas très bien l'utiliser pour initialiser p2, pourriez-vous? Vous devez faire p1 = &p0; pour l'effet que vous voulez. "pointeur vers pointeur" signifie "à cette adresse, vous trouverez un pointeur". Mais si vous regardez l'adresse &a, vous trouvez un tableau (évidemment), donc int ** n'est pas le bon type.

+0

Alors, qu'est-ce qui est stocké sous le nom 'a', sinon une adresse au premier élément de' a' (qui serait le pointeur que je cherchais)? – jpmelos

+3

@jpmelos - 'a' est un tableau. Il stocke les éléments de tableau réels. Le nom d'un tableau se décompose en un pointeur vers le premier élément lorsqu'il est transmis à une fonction, mais cela ne signifie pas que les tableaux sont implémentés comme des pointeurs vers une zone. 'int a [3];' ne fait pas de pointeurs, juste trois 'int's. –

+0

Merci beaucoup! Votre commentaire m'a aidé à éclairer un peu plus mes pensées! – jpmelos