2011-11-21 22 views
6

Desidero assegnare una matrice multidimensionale allocata staticamente a una variabile temporanea. Si consideri il seguente esempio:Come assegnare un array multidimensionale a una variabile temporanea?

void foo(int b[3][2]) 
{ 
    b[1][1] = 1; // no segmentation fault 
} 

int main() 
{ 
    int a[3][2] = {{1, 2}, {11, 12}, {21, 22}}; 

    foo(a); 

    int** c; 
    c = (int**)&a; 
    c[1][1] = 1; // segmentation fault on execution 

    int* d[3]; 
    d[0] = (int*)&(a[0]); 
    d[1] = (int*)&(a[1]); 
    d[2] = (int*)&(a[2]); 
    d[1][1] = 1; // no segmentation fault 

    return 0; 
} 

Fondamentalmente voglio fare quello che il compilatore fa con il parametro b di foo(). Ma l'unica soluzione funzionante che potrei inventare è d. Non c'è un modo meno complicato?

+0

È strano quante persone pensano che un array 2D sia in qualche modo direttamente indirizzato a un puntatore ai puntatori. – tenfour

risposta

11

cdecl (man page) è tuo amico:

cdecl> explain int b[3][2] 
declare b as array 3 of array 2 of int 
cdecl> declare b as pointer to array 2 of int 
int (*b)[2] 

Quindi, provate questo:

void foo(int b[3][2]) 
{ 
    b[1][1] = 1; // no segmentation fault 
} 

int main() 
{ 
    int a[3][2] = {{1, 2}, {11, 12}, {21, 22}}; 

    foo(a); 

    int (*b)[2] = a; 

    b[1][1] = 1; 

    return 0; 
} 
+0

eh - questo è nuovo. dove/cosa è cdecl? – sehe

+0

OMG _cdecl_: D: D: D Non ho mai visto questo: D C'è la versione online: @sehe - http://cdecl.org/ –

+1

+1, grazie per cdecl ;-) –

9

int[3][2] e int** sono tipi incompatibili. Non puoi castare l'uno con l'altro.

Prova questo:

int (*c)[2]; 
c = a; //no need to cast 
c[1][1] = 1; //ok 

Oppure si potrebbe fare questo (dichiarazione così come l'inizializzazione):

int (*c)[2] = a; //no need to cast 
c[1][1] = 1; //ok 

Pollice della regola:

  • Non usare il cast in stile c in C++. Usa il cast di stile C++. Aveva è stato utilizzato C++ - ghisa stile, il compilatore avrebbe detto il problema molto prima (ideone) (non è necessario eseguire il codice per vedere il problema):

    prog.cpp:5: error: invalid static_cast from type ‘int (*)[3][2]’ to type ‘int**’ 
    

    Ma cast di tipo C lo compila bene (ideone), come già sapete.

  • E ogni volta che si utilizza il cast, anche cast in stile C++, il primo dubbio dovrebbe essere il cast stesso se il programma non funziona come previsto.

+1

Hai un errore di battitura :) –

+1

@KirilKirov: corretto. Grazie. – Nawaz

2

Se si utilizza un compilatore piuttosto moderno che supporta abbastanza parti dello standard C++ 11, è possibile utilizzare auto:

int a[3][2] = ...; 
auto &b = a; 
b[1][1] = 1; // a[1][1] will be set 

Naturalmente, sia a e b deve essere definito nello stesso ambito per farlo funzionare. Non si può avere un parametro auto in una funzione, per esempio (questo è ciò che i modelli sono per.)

5

Come probabilmente sapete ormai, dalle altre risposte, il tipo di a non è in realtà equivale a int** - è finite decade (quando restituito/passato per valore).

int (*b)[2] = a; // would solve that 

C'è un altro C modo ++:

typedef std::array<std::array<int, 2>, 3> M23; 

void foo(M23& b) 
{ 
    b[1][1] = 1; 
} 

int main() 
{ 
    M23 a = {{1, 2}, {11, 12}, {21, 22}}; 

    foo(a); 

    M23 d = a; 
    d[1][1] = 1; 
} 
+1

+1 A tutti piace 'std :: array' :-) –

+1

@sehe: Questo è buono, ma si dovrebbe anche rispondere alla domanda e spiegare il problema con il codice OP. Una volta spiegato, puoi suggerire una soluzione alternativa migliore. – Nawaz

1

Non espressi in modo esplicito, in modo da provare a scrivere

c = &a; 

Poi il compilatore GCC (usando gcc -Wall -g bidim.c -o bidim per compilare) la dà avvertimento corretto:

bidim.c:13:7: warning: assignment from incompatible pointer type [enabled by default] 

E quindi dovresti capire che una matrice 2D non è implementata come una matrice di puntatori agli array 1D.

0

La prima cosa che mi viene in mente è utilizzando un typedef e riferimento come

typedef int thing_t[3][2]; 
thing_t& e = a; 
e[1][1] = 1; 

con puntatori

int (*f)[2] = a; 
f[1][1] = 1; 

Un'altra possibilità è quella di incapsulare in struct.

Problemi correlati