2010-04-21 12 views
1

J'ai un tableau 3x3 que j'essaie de créer un pointeur et je continue d'obtenir ce tableau, ce qui donne?Impossible de convertir int [] [] en int *

Comment dois-je définir le pointeur? J'ai essayé toutes les combinaisons de [] et *.

Est-ce possible?

int tempSec[3][3]; 

int* pTemp = tempSec; 
+0

cette question est posée environ 10 fois par jour, a répondu à chaque fois. pourquoi n'est-ce pas fermé? –

+0

Vous devez utiliser un typedef pour vous aider. Voir ci-dessous. –

+0

Fournir un lien en double et je vais voter pour le fermer. – Suma

Répondre

15

Vous pouvez faire int *pTemp = &tempSec[0][0];

Si vous voulez traiter un tableau de 3x3 comme un int *, vous devriez probablement déclarer comme int[9] et utiliser tempSec[3*x+y] au lieu de tempSec[x][y].

Alternativement, peut-être ce que vous vouliez était int (*pTemp)[3] = tempSec? Ce serait alors un pointeur vers le premier élément de tempSec, ce premier élément étant lui-même un tableau.

Vous pouvez en effet prendre un pointeur vers un tableau 2D:

int (*pTemp)[3][3] = &tempSex; 

Vous aurait alors l'utiliser comme ceci:

(*pTemp)[1][2] = 12; 

qui est presque certainement pas ce que vous voulez, mais dans votre commentez que vous l'avez demandé ...

+0

Donc, ce sont mes deux choix? Il n'y a aucun moyen de créer un pointeur vers un tableau 2D? – cam

+3

Oui, mais il n'aura pas le type 'int *'. Je ne peux pas dire quelles parties de votre question sont les parties que vous voulez, et ce que vous ne faites pas ... –

+1

En procédant de cette façon vous jetez toute information sur la disposition des données. Maintenant, vous ne pouvez pas dire que c'est un tableau trois par trois. –

0
int a[20][30]; 
int* b=&a[0][0]; 
0

Le message original suit - veuillez ne pas tenir compte, il est mal informé. Laissant cela pour la postérité;)

Cependant, here is a link I found regarding memory allocation of 2-dimensional arrays in c++. Peut-être que cela pourrait avoir plus de valeur.


Je ne sais pas c'est ce que vous voulez, et ça a été un moment que je l'ai écrit C++, mais la raison pour laquelle votre casting échoue est parce que vous allez à partir d'un tableau de tableaux à un pointeur de ints. Si, d'autre part, vous avez essayé de tableau à tableau à un pointeur de pointeurs, il serait probablement travailler

int tempSec[3][3]; 
int** pTemp = tempSec; 

rappelez-vous, votre tableau de tableaux est vraiment un bloc contigu de mémoire contenant des pointeurs vers d'autres blocs contigus de la mémoire - c'est pourquoi le fait de lancer un tableau de tableaux dans un tableau d'ints vous donnera un tableau de ce qui ressemble à de la foutaise [cette poubelle est vraiment des adresses de mémoire!].

Encore une fois, cela dépend de ce que vous voulez. Si vous le voulez au format pointeur, le pointeur de pointeurs est le chemin à parcourir. Si vous voulez tous les 9 éléments comme un tableau contigu, vous devrez effectuer une linéarisation de votre double tableau.

+0

"votre tableau de tableaux est vraiment un bloc contigu de mémoire contenant des pointeurs vers d'autres blocs de mémoire contigus". Non, c'est vraiment, vraiment pas. –

+0

"votre tableau de tableaux est vraiment un bloc contigu de pointeurs de mémoire" --- dans ce cas, c'est faux. Un tableau déclaré 'int arr [3] [3]' est un bloc contigu de mémoire assez grand pour 9 'int', avec un accès par des offsets calculés. Je pense que beaucoup de programmeurs C supposent que tous les tableaux multidimensionnels sont des pointeurs vers des pointeurs (et ainsi de suite ...) à cause de 'char ** argv' --- mais rappelez-vous qu'il s'agit d'un tableau de' char * ', c'est-à-dire un tableau de chaînes. En général, seuls les tableaux multidimensionnels «irréguliers» sont implémentés en tant que couches multiples d'indirection (et ceci est fait à la discrétion du programmeur). –

+0

@Derrick Turk, merci pour les commentaires utiles! plus rustre que je me souviens;) –

0

Comme Steve l'a souligné, la forme appropriée est int *pTemp = &tempSec[0][0];. int** pTemp2 = tempSec; ne fonctionne pas. L'erreur est donnée:

cannot convert 'int (*)[3]' to 'int**' in initialization 

Ce n'est pas stocké sous la forme d'un tableau de pointeurs vers des tableaux. Il est stocké comme un grand vecteur, et le compilateur cache le [a][b] = [a*rowLength+b] de votre part.

#include <iostream> 
using namespace std; 
int main() 
{ 
    // Allocate on stack and initialize. 
    int tempSec[3][3]; 
    int n = 0; 
    for(int x = 0; x < 3; ++x) 
     for(int y = 0; y < 3; ++y) 
      tempSec[x][y] = n++; 

    // Print some addresses. 
    cout << "Array base: " << size_t(tempSec) << endl; 
    for(int x = 0; x < 3; ++x) 
     cout << "Row " << x << " base: " << size_t(tempSec[x]) << endl; 

    // Print contents. 
    cout << "As a 1-D vector:" << endl; 
    int *pTemp = &tempSec[0][0]; 
    for(int k = 0; k < 9; ++k) 
     cout << "pTemp[" << k << "] = " << pTemp[k] << endl; 
    return 0; 
} 

sortie:

Array base: 140734799802384 
Row 0 base: 140734799802384 
Row 1 base: 140734799802396 
Row 2 base: 140734799802408 
As a 1-D vector: 
pTemp[0] = 0 
pTemp[1] = 1 
pTemp[2] = 2 
pTemp[3] = 3 
pTemp[4] = 4 
pTemp[5] = 5 
pTemp[6] = 6 
pTemp[7] = 7 
pTemp[8] = 8 

Notez que la rangée 0 adresse est la même que l'adresse de rangée complète et rangées consécutives sont décalés par sizeof(int) * 3 = 12.

6

Son easyier d'utiliser un typedef

typedef int ThreeArray[3]; 
typedef int ThreeByThree[3][3]; 

int main(int argc, char* argv[]) 
{ 
    int   data[3][3]; 

    ThreeArray* dPoint = data; 
    dPoint[0][2]   = 5; 
    dPoint[2][1]   = 6; 

    // Doing it without the typedef makes the syntax very hard to read. 
    // 
    int(*xxPointer)[3] = data; 
    xxPointer[0][1]  = 7; 

    // Building a pointer to a three by Three array directly. 
    // 
    ThreeByThree* p1  = &data; 
    (*p1)[1][2]   = 10; 

    // Building a pointer to a three by Three array directly (without typedef) 
    // 
    int(*p2)[3][3]  = &data; 
    (*p2)[1][2]   = 11; 

    // Building a reference to a 3 by 3 array. 
    // 
    ThreeByThree& ref1 = data; 
    ref1[0][0]   = 8; 

    // Building a reference to a 3 by 3 array (Without the typedef) 
    // 
    int(&ref2)[3][3]  = data; 
    ref2[1][1]   = 9; 


    return 0; 
} 
+0

Cela supprime l'une des dimensions du tableau, ce qui est exactement ce que vous avez indiqué sur ma réponse. Alors maintenant, je suis confus de ce que vous étiez sur. –

+0

@Steve Jessop: Vous jetez les deux dimensions. Je n'en jette qu'un. Convertir en un pointeur que vous allez perdre une dimension, vous ne pouvez pas aider cela. Si nous sommes convertis en référence, vous n'avez pas besoin de perdre une dimension. –

+0

En plus de la première ligne de ma réponse, j'ai donné la même réponse que vous, mais sans le typedef. De toute façon, vous pouvez * éviter * de perdre des dimensions, en les incluant toutes dans le type du pointeur. Il est peu probable que c'est ce que le questionneur veut, mais il est tout à fait clair pour moi si le questionneur veut spécifiquement un int, ou veut juste une sorte de pointeur vers un tableau. C'est pourquoi j'ai mentionné les deux. –

0

Une autre façon de s'y prendre, est d'abord créer un tableau de pointeurs:

int* pa[3] = { temp[0], temp[1], temp[2] }; 

Ensuite, créez un pointeur de pointeur pour pointer vers ce :

int** pp = pa; 

Vous pouvez ensuite utiliser la syntaxe de tableau normale sur ce pointeur de pointeur pour obtenir l'élément vous e recherche:

int x = pp[1][0]; // gets the first element of the second array 

En outre, si la seule raison pour laquelle vous essayez de le convertir en un pointeur est si vous pouvez passer à une fonction, vous pouvez le faire:

void f(int v[3][3]); 

Comme Tant que la taille des tableaux est fixe, vous pouvez passer un tableau bidimensionnel à une fonction comme celle-ci. C'est beaucoup plus spécifique que le passage d'un pointeur.

+0

Cette signature pour 'f' ne supprime-t-elle pas l'une des dimensions? C'est aussi le cas de 'void f (int (* v) [3]);', en fait un pointeur vers un tableau plutôt qu'un tableau de tableaux. Donc, bien qu'il soit plus spécifique que de simplement passer un 'int **', ce n'est pas aussi spécifique que vous pourriez le penser. Il est un peu trompeur de mettre un nombre dans la dernière dimension, puisque le compilateur l'ignore, mais c'est un indice pour l'appelant à quel point un tableau est censé passer. –

+0

Où par la dernière dimension, bien sûr je veux dire la première dimension ... –

+0

Évidemment, le compilateur vous permettra de faire toutes sortes de choses folles sans se plaindre. Et oui, mon point était que ce serait beaucoup plus clair pour l'utilisateur. –

3

Oh. C'est facile! Vous pouvez réellement utiliser cette technique impressionnante pour le mouler dans d'autres types merveilleux. Par exemple:

int aai[3][3]; 
int (__stdcall *pfi_lds)(long, double, char*) = reinterpret_cast<int (__stdcall *)(long, double, char*)>(aai); 

N'est-ce pas que gonfler? La question est de savoir si c'est significatif.

Vous demandez comment mentir à votre compilateur. Donc, la première chose à savoir est: Pourquoi voulez-vous mentir?

+0

Ouais, ce n'est vraiment pas une bonne idée ... –

+0

Pourquoi le feriez-vous? Il est parfaitement légal d'obtenir l'adresse du premier membre. –

0

Demandons cdecl.org traduire votre déclaration pour nous:

int tempSec[3][3] 

retours

declare tempSec as array 3 of array 3 of int 


Ok, alors comment pouvons-nous créer un pointeur sur cette?Demandons cdecl à nouveau:

declare pTemp as pointer to array 3 of array 3 of int 

retours

int (*pTemp)[3][3] 


Puisque nous avons déjà le tableau 3 du tableau 3 int, nous pouvons simplement faire:

int (*pTemp)[3][3] = &tempSec;