2011-03-05 16 views
18

Sono un programmatore Ruby che ha finito per sviluppare un codice generato per C. È come chiedere a una Limousine di trainare un camion degli anni '60. Comunque.Come restituire un array 2D a una funzione in C?

Ecco cosa ho pensato dovrebbe funzionare ma non funziona.

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

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

//inside main 
drawLine(pixels()); 

ho sbattuto la testa sulla mia scrivania cercando di ottenere questo lavoro cosa. Per favore aiuto.

+4

Questo potrebbe interessare http://stackoverflow.com/questions/4570366/pointer-to-local-variable – jweyrich

+0

quello che sembra essere il problema ? –

+0

@SOE Leggi la risposta di Mahesh per capire qual è il problema. –

risposta

4

Grazie a tutti per le vostre risposte e in particolare per la spiegazione dettagliata della relazione tra puntatori e array.

ho incapsulati la matrice in una struttura

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

Questa è una soluzione piuttosto buona, basti sapere che se si tratta di array di grandi dimensioni e il tuo compilatore non è in grado di ottimizzare potresti finire per creare copie inutili. – user470379

1

Il modo più semplice è destinata probabilmente ad essere dichiara la matrice float in principale e avendo pixels basta riempirlo:

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

È anche possibile utilizzare malloc e free e memorizzare i pixel sul mucchio, ma se questo è tanto più grande sarà l'array di pixel, non c'è davvero bisogno e aggiunge solo ulteriore complessità per assicurarsi che la memoria venga sempre allocata e liberata correttamente.

+0

L'approccio è corretto. L'unica preoccupazione che sento è che dal momento che la nostra applicazione dovrebbe funzionare su un dispositivo integrato, la check list di revisione del codice chiede di ridurre al minimo le vars globali. Il codice avrà centinaia di funzioni simili a pixel. –

+0

@Akshar Non uso vars globali ... I #define un paio di cose, ma se volessi davvero potresti semplicemente ripetere i 2 ovunque, ma ti stai preparando per un grande mal di testa di manutenzione in qualsiasi momento di questi valori cambiano e/o molto difficile eseguire il debug dei bug se qualcuno ottiene una nuova dimensione sbagliata. – user470379

20

Poverina. In C, i puntatori e gli array sono strettamente correlati. Inoltre, di solito è necessario passare la dimensione di un array come variabile separata. Diciamo Si inizia 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

Ho appena provato per questo codice-snippet e ho ottenuto: "errore: conversione non valida da 'void *' a 'float *'" in createArray.È necessario aggiungere un cast: "float * values ​​= (float *) calloc (m * n, sizeof (float)); " ..lo stesso per il float ** – Alex

+1

@Alex È possibile compilarlo come se fosse codice C++? È valido C e C++ non valido. – aschepler

2

In C/C++, quando si passa un array a una funzione, decade ad essere un puntatore che punta al primo elemento della matrice. Quindi, nella funzione pixels(), si restituisce l'indirizzo di una variabile allocata nello stack. L'indirizzo della variabile di restituzione non è più valido perché al ritorno pixels(), la variabile allocata allo stack non rientra nell'ambito. Quindi, dovresti invece per una variabile la cui memoria è dinamica (cioè, usando malloc, calloc).

Quindi, per un array bidimensionale, è possibile utilizzare float** arrayVariable;. Inoltre, se si passa a una funzione, si dovrebbe essere cauti su quante righe ha & colonne.

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 
} 

Dal momento che, matrice 2D è la gestione delle risorse è di per sé, dovrebbe restituire le risorse di nuovo al deposito gratuitamente utilizzando libera.

+0

Immagino tu voglia che io usi malloc all'interno della funzione pixel. Allora ho bisogno di ricordarmi di liberarlo pure. –

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

Hai la sola risposta corretta qui! Peccato che tu non abbia spiegato nulla. Se hai aggiunto qualche spiegazione, sentiti libero di lasciare un commento a me, controllerò e ascolterò se penso che sia buono. – Olaf

Problemi correlati