Que fait le code suivant?
int g[] = {9,8};
int (*j) = g;
De ma compréhension, il crée un pointeur vers un tableau de 2 pouces. Mais alors pourquoi ça marche:
int x = j[0];
et cela ne fonctionne pas:
int x = (*j)[0];
Les parenthèses sont superflues dans votre exemple. Le pointeur ne se soucie pas de la présence d'un tableau - il sait seulement que son pointage vers un int
int g[] = {9,8};
int (*j) = g;
pourrait également être réécrit
int g[] = {9,8};
int *j = g;
qui pourrait également être réécrit comme
int g[] = {9,8};
int *j = &g[0];
un pointeur vers un tableau ressemblerait
int g[] = {9,8};
int (*j)[2] = &g;
//Dereference 'j' and access array element zero
int n = (*j)[0];
Il y a une bonne lecture sur les déclarations de pointeur (et comment les bloquer) sur ce lien ici: http://www.codeproject.com/Articles/7042/How-to-interpret-complex-CC-declarations =
int g[] = {9,8};
Cela déclare un objet de type int [2] et initialise ses éléments à {9,8}
int (*j) = g;
Cela déclare un objet de type int * et l'initialise avec un pointeur sur le premier élément de g .
Le fait que la deuxième déclaration initialise j avec autre chose que g est assez étrange. C et C++ ont juste ces règles étranges sur les tableaux, et c'est l'un d'entre eux. Ici l'expression g
est implicitement convertie d'une valeur l faisant référence à l'objet g en une valeur r de type int*
qui pointe vers le premier élément de g.
Cette conversion se produit à plusieurs endroits. En fait, cela se produit lorsque vous faites g[0]
. L'opérateur d'index de tableau ne fonctionne pas réellement sur les tableaux, uniquement sur les pointeurs. Donc, la déclaration int x = j[0];
fonctionne parce que g[0]
arrive à faire la même conversion implicite qui a été effectuée lorsque j
a été initialisé.
Un pointeur vers un tableau est déclaré comme ceci
int (*k)[2];
et vous avez tout à fait raison sur la façon dont cela serait utilisé
int x = (*k)[0];
(notez comment "la déclaration suit l'utilisation" , c'est-à-dire la syntaxe pour déclarer une variable d'un type imite la syntaxe de en utilisant une variable de ce type.)
Cependant, on n'utilise généralement pas de pointeur vers un tableau. Le but des règles spéciales concernant les tableaux est que vous puissiez utiliser un pointeur sur un élément de tableau comme s'il s'agissait d'un tableau. Donc, C idiomatique ne se soucie généralement pas que les tableaux et les pointeurs ne sont pas la même chose, et les règles vous empêchent de faire beaucoup de choses utiles directement avec les tableaux. (par exemple, vous ne pouvez pas copier un tableau comme: int g[2] = {1,2}; int h[2]; h = g;
)
Exemples:
void foo(int c[10]); // looks like we're taking an array by value.
// Wrong, the parameter type is 'adjusted' to be int*
int bar[3] = {1,2};
foo(bar); // compile error due to wrong types (int[3] vs. int[10])?
// No, compiles fine but you'll probably get undefined behavior at runtime
// if you want type checking, you can pass arrays by reference (or just use std::array):
void foo2(int (&c)[10]); // paramater type isn't 'adjusted'
foo2(bar); // compiler error, cannot convert int[3] to int (&)[10]
int baz()[10]; // returning an array by value?
// No, return types are prohibited from being an array.
int g[2] = {1,2};
int h[2] = g; // initializing the array? No, initializing an array requires {} syntax
h = g; // copying an array? No, assigning to arrays is prohibited
Parce que les tableaux sont tellement incohérents avec les autres types en C et C++, vous devez simplement les éviter. C++ a std::array
qui est beaucoup plus cohérent et vous devez l'utiliser lorsque vous avez besoin de tableaux de taille statique. Si vous avez besoin de tableaux de taille dynamique, votre première option est std :: vector.
j[0];
déréférence un pointeur sur int
, donc son type est int
.
(*j)[0]
n'a pas de type. *j
déréférence un pointeur vers un int
, il renvoie donc un int
et (*j)[0]
tente de déréférencer un int
. C'est comme essayer int x = 8; x[0];
.