web-dev-qa-db-fra.com

pointeur vers le tableau c ++

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];
20
Sam Adamsh

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 =

40
Ben Cottrell
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.

22
bames53

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];.

9
Luchian Grigore