2011-11-21 28 views
6

Quiero asignar una matriz multidimensional asignada estáticamente a una variable temporal. Consideremos el siguiente ejemplo:¿Cómo asignar una matriz multidimensional a una variable temporal?

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; 
} 

Básicamente quiero hacer lo que el compilador hace con el parámetro de bfoo(). Pero la única solución de trabajo que pude encontrar es d. ¿No hay una forma menos complicada?

+0

Es extraño cuántas personas piensan que una matriz 2D de alguna manera arroja directamente a un puntero a punteros. – tenfour

Respuesta

11

cdecl (man page) es su amigo:

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] 

Así, intente esto:

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

huh - eso es nuevo. donde/que es cdecl? – sehe

+0

OMG _cdecl_: D: D: D Nunca he visto esto: D Hay versión en línea: @sehe - http://cdecl.org/ –

+1

+1, gracias por cdecl ;-) –

9

int[3][2] y int** son tipos incompatibles. No puedes lanzar uno a otro.

Prueba esto:

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

O usted podría hacer esto (la declaración, así como la inicialización):

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

pulgar de regla:

  • No use elenco estilo c en C++. Use el molde de estilo C++. Había que utilizó C++ - Reparto estilo, el compilador te habría dicho el problema mucho antes (ideone) (sin necesidad de ejecutar el código para ver el problema):

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

    Pero conversión de estilo C compila bien (ideone), como ya sabes.

  • Y siempre que use elenco, incluso molde de estilo C++, su primera duda debería ser el reparto si el programa no funciona como se esperaba.

+1

Tiene un error tipográfico :) –

+1

@KirilKirov: Reparado. Gracias. – Nawaz

2

Si está utilizando un compilador bastante moderno que soporta bastantes partes del estándar C++ 11, puede utilizar auto:

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

Por supuesto, tanto a y b es a determinar en el mismo alcance para que funcione. No se puede tener un parámetro auto en una función, por ejemplo, (eso es lo que las plantillas son para.)

5

Como usted probablemente sabe ahora, a partir de las otras respuestas, el tipo de a en realidad no es equivalente a int** - que jsut se descompone a eso (cuando se devuelve/pasa por valor).

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

Hay una mayor C manera ++:

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 todo el mundo le gusta 'std :: array' :-) –

+1

@sehe: Esto es bueno, pero también debe responder la pregunta y explicar el problema con el código de OP. Una vez que haya explicado eso, puede sugerir una mejor solución alternativa. – Nawaz

1

No convertir explícitamente, a fin de tratar de escribir

c = &a; 

A continuación, el compilador GCC (usando gcc -Wall -g bidim.c -o bidim para compilar) que la da advertencia correcta:

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

Y luego debe tener en cuenta que una matriz 2D no está implementada como una matriz de punteros a arrays 1D.

0

La primera cosa que viene a la mente es el uso de un typedef y referencia como

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

Con punteros

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

Otra posibilidad es encapsular en struct.

Cuestiones relacionadas