Declarando uma function C para retornar uma matriz

Como posso fazer uma function que retorna um array? Eu tentei isso

const int WIDTH=11; const int HEIGHT=11; int main() { char A[WIDTH][HEIGHT]; A=rand_grid(WIDTH,HEIGHT); return 0; } // Initializes a random board. char[][] rand_grid(int i, int k) { char* A[i][k]; for(j=0;j<i;++j) { for(l=0;l<k;++l) { A[j][l]=ran(10); } } return A; } // Returns a random number from the set {0,...,9}. int ran(int i) { srand((unsigned int) time(0)); return(rand()%10); } 

Várias coisas para apontar.

Primeiro de tudo, você não pode atribuir um object de matriz como você faz aqui:

 char A[WIDTH][HEIGHT]; A=rand_grid(WIDTH,HEIGHT); 

Objetos do tipo array não são modificáveis.

Em segundo lugar, as funções em C não podem retornar tipos de matriz. Eles podem retornar pointers para matrizes, embora:

 char (*foo(int width))[HEIGHT] { /** * dynamically allocate memory for a widthxHEIGHT array of char */ char (*newArr)[HEIGHT] = malloc(sizeof *newArr * width); /** * initialize array contents here */ return newArr; } 

A syntax é um pouco confusa; lê como

  foo -- foo foo(int width) -- is a function -- taking an int parameter *foo(int width) -- returning a pointer (*foo(int width))[HEIGHT] -- to a HEIGHT-element array char (*foo(int width))[HEIGHT] -- of char 

Para C89, HEIGHT no snippet acima deve ser uma expressão integral de constante de tempo de compilation (uma macro, um literal numérico ou uma expressão aritmética consistindo de macros e / ou literais numéricos). Eu não tenho certeza se isso também é verdade para C99.

Com base no trecho que você postou, o que você quer fazer é pegar uma matriz que você já alocou e inicializar seu conteúdo. Lembre-se de que, na maioria dos contextos, uma expressão de um tipo de matriz será implicitamente convertida em um ponteiro para o tipo base. IOW, se você passar uma matriz de elementos N de T para uma function, o que a function realmente recebe é um ponteiro para T:

 void foo (T *p) {...} ... T arr[N]; foo(arr); 

Para matrizes de 2-d, é um pouco mais feio:

 void foo (T (*p)[M]) {...} ... T arr[N][M]; foo(arr); 

Isso também depende de M ser conhecido em tempo de compilation, o que limita a utilidade da function. O que você gostaria é de uma function que possa lidar com um array bidimensional de tamanho arbitrário. A melhor maneira que eu conheço para conseguir isso é em vez de passar um ponteiro para o array, passar o endereço do primeiro elemento no array [1] e passar o número de linhas e colunas como parâmetros separados:

 void foo(T *base, size_t rows, size_t cols) {...} ... T arr[N][M]; foo (&arr[0][0], N, M); 

Então sua function rand_grid seria algo como isto:

 void rand_grid(char *base, size_t rows, size_t cols) { size_t i, j; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { /** * Since base is a simple char *, we must index it * as though it points to a 1-d array. This works if * base points to the first element of a 2-d array, * since multi-dimensional arrays are contiguous. */ base[i*cols+j] = initial_value(); } } } int main(void) { char A[WIDTH][HEIGHT]; rand_grid(&A[0][0], WIDTH, HEIGHT); ... } 

  1. Mesmo que as expressões &A[0][0] e A produzam o mesmo valor (o endereço base de A), os tipos das duas expressões são diferentes. A primeira expressão é avaliada como um ponteiro simples para char ( char * ), enquanto a segunda é avaliada como um ponteiro para uma matriz 2D de char ( char (*)[HEIGHT] ).

Você não pode. Você pode passar o ponteiro para array como um parâmetro e modificá-lo, ou a própria function pode alocar dados e retornar o ponteiro.

no seu caso

 void rand_grid(char A[WIDTH][HEIGHT]) { A[0][0] = 'A'; // or whatever you intend to do } main() { char A[WIDTH][HEIGHT]; rand_grid(A); } 

Edit : Como caf apontou pode-se realmente retornar a struct com uma matriz, mas é claro que nenhum programador-C em seu juízo perfeito faria isso.

Você nunca pode retornar uma variável alocada em pilha (” auto “) de algo diferente de um tipo primitivo (valor) e struct s de tal. Para outros tipos, você precisa alocar a memory do heap, usando malloc() , ou quebrar a matriz (tamanho fixo) em uma struct .

Se você estiver usando uma matriz de tamanho fixo, você pode modelá-lo como uma struct e usar struct-return:

 #define WIDTH 11 #define HEIGHT 11 typedef struct { unsigned char cell[WIDTH * HEIGHT]; } Board; Board board_new(void) { Board b; size_t i; for(i = 0; i < sizeof b.cell / sizeof *b.cell; i++) b.cell[i] = rand() & 255; return b; } 

Isso é bom, e não deve ser mais caro do que a alternativa, de usar um ponteiro explícito:

 void board_init(Board *b); 

Desde o primeiro caso de struct-return pode ser reescrito (pelo compilador) para o último. Isso é chamado de otimização do valor de retorno .

Se você realmente quiser fazer isso, você pode tentar tornar a matriz A estática, desta forma o armazenamento para A não é determinado pelo escopo da function e você pode retornar a matriz (em forma de ponteiro, é claro).

Mas esta não é uma boa maneira de realizar o que você está tentando alcançar, em vez disso, passar a matriz para funcionar rand_grid . Isso é o que passar por endereço é destinado.

Todos os methods que conheço para retornar um array de uma function têm pontos fracos e fortes.

Embrulhar em um struc evita a sobrecarga de alocar e liberar memory, bem como evita que se lembre de liberar. Você tem esses problemas em qualquer solução que usa malloc, calloc e realloc. Por outro lado, envolver em uma estrutura requer conhecer o tamanho máximo possível da matriz e é decididamente um desperdício de memory e tempo de execução para matrizes grandes (por exemplo, carregar um arquivo na memory e passar o conteúdo do arquivo de function para function copiando).