Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declaring a C function to return an array

Tags:

c

How can I make a function which 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); } 
like image 446
Jaska Avatar asked Sep 21 '09 08:09

Jaska


People also ask

In what way an array can be returned from a function?

We can also make a function return an array by declaring it inside a structure in C++. Let us see how. Here, note that we have declared the array arr inside the structure demo . And this time the function has a return type of the structure itself and return demo_mem (structure variable) instead of the array.

Why can't you return an array in C?

C returns by value. Arrays cannot be passed by value, therefore they cannot be returned.


2 Answers

Several things to point out.

First of all, you cannot assign an array object as you do here:

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

Objects of array type are not modifiable.

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

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 little confusing; it reads as

       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 must be a compile-time constant integral expression (either a macro, a numeric literal, or an arithmetic expression consisting of macros and/or numeric literals). I'm not sure if that's also true for C99.

Based on the snippet you've posted, what you want to do is to take an array you've already allocated and initialize its contents. Remember that in most contexts, an expression of an array type will implicitly be converted to a pointer to the base type. IOW, if you pass an N-element array of 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-d arrays, it's a little uglier:

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

This also relies on M being known at compile time, which limits the function's usefulness. What you'd like is a function that can deal with a 2-d array of arbitrary size. The best way I know of to accomplish this is instead of passing 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 would 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);   ... } 

  1. Even though the expressions &A[0][0] and A yield the same value (the base address of A), the types of the two expressions are different. The first expression evaluates to a simple pointer to char (char *), while the second evaluates to a pointer to a 2-d array of char (char (*)[HEIGHT]).
like image 143
John Bode Avatar answered Oct 09 '22 20:10

John Bode


You can't. You can either pass pointer to array as a parameter and have function modify it, or the function itself can allocate data and return 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); } 

Edit: As caf pointed out one can actually return the struct with an array in it, but of course no c-programmer in their right mind would do that.

like image 45
Michael Krelin - hacker Avatar answered Oct 09 '22 19:10

Michael Krelin - hacker