Declaring a C function to return an array

How can I create a function that returns an array? I tried this

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); } 
+46
c
Sep 21 '09 at 8:26
source share
5 answers

A few things to point out.

First of all, you cannot assign an array object like you are here:

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

Array type objects are not modified.

Secondly, functions in C cannot return array types. They can return pointers to arrays:

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

The syntax is a bit confusing; it reads like

  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 

For C89, HEIGHT in the above snippet should be a constant integral expression of compilation time (either a macro, a numeric literal, or an arithmetic expression consisting of macros and / or numeric literals). I am not sure if this is also true for the C99.

Based on the fragment that you posted, you want to make an array that you have already allocated and initialize its contents. Remember that in most contexts, an array type expression will be implicitly converted to a pointer to the base type. IOW, if you pass an N-element array from T to a function, what the function actually receives is a pointer to T:

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

For 2-dimensional arrays this is a bit uglier:

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

It also depends on what M is known at compile time, which limits the usefulness of the function. What you need is a function that can work with a 2-dimensional array of arbitrary size. The best way I know this is to not pass a pointer to the array, pass the address of the first element in the array [1], and pass the number of rows and columns as separate parameters:

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

So your rand_grid function will look something like this:

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



  • Even if the expressions &A[0][0] and A give the same value (base address A), the types of these two expressions are different. The first expression evaluates to a simple pointer to char ( char * ), and the second evaluates to a pointer to the 2nd array of char ( char (*)[HEIGHT] ).
+79
Sep 21 '09 at 15:05
source share

You can not. You can either pass a pointer to an array as a parameter, or change its function, or the function itself can select data and return a pointer.

in your case

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

Change As indicated in the application, you can actually return a struct with an array in it, but, of course, a c-programmer in his right mind will not do this.

+15
Sep 21 '09 at 8:27
source share

You can never return a variable selected by the stack (" auto ") for something other than the primitive type (value) and struct . For other types, you need to allocate memory from the heap using malloc() or wrap an array (fixed size) in a struct .

If you use a fixed-size array, you can model it as a struct and use 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; } 

This is good and should not be more expensive than the alternative of using an explicit pointer:

 void board_init(Board *b); 

Since the first case of struct-return can be rewritten (by the compiler) to the latter. This is called return value optimization .

+11
21 Sep '09 at 8:27
source share

If you really want to do this, you can try to make the array A static, so the storage for A is not determined by the scope of the function, and you can actually return the array (as a pointer, of course).

But this is not the best way to accomplish what you are trying to achieve, pass the array to the rand_grid function rand_grid . What pass through address means.

+1
Sep 21 '09 at 9:16
source share

All the methods that I know of, return an array from a function, have weaknesses and strengths.

The flow around the structure eliminates the overhead of allocating and freeing memory, and also avoids memorization. You have problems with any solution that uses malloc, calloc and realloc. On the other hand, the wrapper in the structure requires knowledge of the maximum possible size of the array and, of course, wasteful memory and runtime for large arrays (for example, loading a file into memory and transferring the contents of the file from function to function by copying).

0
Mar 10 '15 at 18:08
source share



All Articles