2011-03-05 22 views
18

Soy un programador de Ruby que ha terminado desarrollando un código para generar C. Es como pedirle a un Limo que remolque un camión de los años sesenta. De todas formas.¿Cómo devolver una matriz 2D a una función en C?

Esto es lo que pensé que debería funcionar pero no funciona.

float[][] pixels() 
{ 
    float x[][]= { {1,1},{2,2} }; 
    return x 
} 

void drawLine(float x[][2]) 
{ 
    //drawing the line 
} 

//inside main 
drawLine(pixels()); 

He golpeado mi cabeza en mi escritorio tratando de hacer que esto funcione. Por favor ayuda.

+4

Esta vez te interesa http://stackoverflow.com/questions/4570366/pointer-to-local-variable – jweyrich

+0

lo que parece ser el problema ? –

+0

@SOE Lea la respuesta de Mahesh para comprender cuál es el problema. –

Respuesta

4

Gracias a todos por sus respuestas y más específicamente por la explicación detallada de la relación matriz-puntero.

que encapsula la matriz en una estructura

struct point_group1 { 
     float x[3]; 
     float y[3]; 
}; 

struct point_group1 pixels(){ 
    struct point_group1 temp; 

    temp.x[0] = 0.0; 
    temp.x[1] = 1.0; 
    temp.x[2] = -1.0; 

    temp.y[0] = 0.0; 
    temp.y[1] = 1.0; 
    temp.y[2] = 1.0; 

    return temp;  
} 



struct point_group1 points1 = pixels(); 
axPoly(points1.x, points1.y ,3, 0.0); 
+0

Esta es una solución bastante buena, solo tenga en cuenta que si se trata de matrices de gran tamaño y su compilador no es bueno para optimizar puede terminar creando copias innecesarias. – user470379

1

La forma más sencilla es probablemente va a ser la que se declara la matriz float en principal y que tiene pixels simplemente llenarlo:

#define PIXEL_X_SIZE 2 
#define PIXEL_Y_SIZE 2 

int pixels(float x[][PIXEL_X_SIZE], int len) { 
    /* I don't know if you want the logic of this method to ever change, 
     but this will be roughly equivalent to what you do above */ 
    if (len < PIXEL_Y_SIZE) { 
     /* the length of the passed array is too small, abort */ 
     return -1; 
    } 

    x[0][0] = x[0][1] = 1; 
    x[1][0] = x[1][1] = 2; 
    return 0; 
} 

void drawLine(float x[][PIXEL_X_SIZE]) { 
    /* this will work fine */ 
} 

int main() { 
    float pixel_array[PIXEL_Y_SIZE][PIXEL_X_SIZE]; 
    pixels(pixel_array, PIXEL_Y_SIZE); 
    drawLine(pixel_array); 
} 

También puede utilizar malloc y free y almacenar los píxeles en el montón, pero si esto Cuanto más grande sea el conjunto de píxeles, realmente no es necesario y solo agrega complejidad adicional para garantizar que su memoria siempre se asigne y libere correctamente.

+0

Tu aproximación está bien. La única preocupación que siento es que, dado que se espera que nuestra aplicación se ejecute en un dispositivo integrado, la lista de verificación de revisión de código solicita minimizar los valores globales. El código tendrá cientos de funciones similares a píxeles. –

+0

@Akshar No uso ningún vars global ... Definí un par de cosas, pero si realmente quisiera, podría repetir el 2 en todas partes, pero se está preparando para un gran dolor de cabeza de mantenimiento en cualquier momento de esos valores cambian y/o son muy difíciles de solucionar errores si alguien obtiene un nuevo tamaño incorrecto. – user470379

20

Pobrecito. En C, los punteros y matrices están estrechamente relacionados. Además, generalmente necesita pasar el tamaño de una matriz como una variable separada. Vamos a empezar con:

#include <stdio.h> 

float** createArray(int m, int n) 
{ 
    float* values = calloc(m*n, sizeof(float)); 
    float** rows = malloc(n*sizeof(float*)); 
    for (int i=0; i<n; ++i) 
    { 
     rows[i] = values + i*m; 
    } 
    return rows; 
} 

void destroyArray(float** arr) 
{ 
    free(*arr); 
    free(arr); 
} 

void drawLine(const float** coords, int m, int n); 

int main(void) 
{ 
    float** arr = createArray(2,2); 
    arr[0][0] = 1; 
    arr[0][1] = 1; 
    arr[1][0] = 2; 
    arr[1][1] = 2; 
    drawLine(arr, 2, 2); 
    destroyArray(arr); 
} 
+0

Acabo de probar este código-snippetand got: "error: conversión inválida de 'void *' a 'float *'" en createArray. Debes agregar un molde: "float * values ​​= (float *) calloc (m * n, sizeof (float)); ..lo mismo para el flotador ** – Alex

+1

@Alex ¿Lo compila posiblemente como si fuera código C++? Es válido C y no válido C++. – aschepler

2

En C/C++, cuando se pasa una matriz a una función, que se descompone a ser un puntero que apunta al primer elemento de la matriz. Entonces, en la función pixels(), está devolviendo la dirección de una variable asignada de pila. La dirección de la variable de retorno ya no es válida porque en el retorno pixels(), la variable asignada de pila queda fuera del alcance. Por lo tanto, en su lugar, debe hacerlo para una variable cuyo almacenamiento sea dinámico (es decir, que use malloc, calloc).

Por lo tanto, para una matriz bidimensional, puede usar float** arrayVariable;. Además, si pasa esto a una función, debe tener cuidado de cuántas filas tiene & columnas.

int rows, columns; 

float** pixels() 
{ 
    // take input for rows, columns 
    // allocate memory from free store for the 2D array accordingly 
    // return the array 
} 

void drawLine(float** returnedArrayVariable) 
{ 
    //drawing the line 
} 

Dado que, matriz 2D es la gestión de los recursos en sí, debe devolver los recursos a la tienda gratis con libre.

+0

Supongo que quieres que use malloc dentro de la función de píxeles. Entonces necesito recordar liberarlo también. –

1
float (*pixels(void))[2] 
{ 
    static float x[2][2]= { {1,1},{2,2} }; 
    return x; 
} 

void drawLine(float (*x)[2]) 
{ 
    //drawing the line 
    //x[0][0]; 
} 

//inside main 
drawLine(pixels()); 
+0

¡Usted tiene la única respuesta correcta aquí! Lástima que no hayas explicado nada. Si ha agregado alguna explicación, siéntase libre de dejarme un comentario, revisaré y votaré si creo que es bueno. – Olaf

Cuestiones relacionadas