9

I have tried this but it won't work:

#include <stdio.h>

    int * retArr()
    {
    int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
    return a;
    }

    int main()
    {
    int a[3][3] = retArr();
    return 0;
    }

I get these errors:

Error 3 error C2075: 'a' : array initialization needs curly braces
4 IntelliSense: return value type does not match the function type

What am I doing wrong?

3
  • Please post what kind of error you are getting Commented Nov 15, 2012 at 2:07
  • 3
    Needs to not to that at all. You're returning the address of a local stack variable that is undefined the moment you leave scope. The pointer-incompatibility is just salt in the wound. Commented Nov 15, 2012 at 2:10
  • Out of interest, why do you want to return a 2D array from a function? There could be a good reason to want to do it, but it is quite possibly not the way to go... Commented Nov 15, 2012 at 2:47

7 Answers 7

8

A struct is one approach:

struct t_thing { int a[3][3]; };

then just return the struct by value.

Full example:

struct t_thing {
    int a[3][3];
};

struct t_thing retArr() {
    struct t_thing thing = {
        {
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
        }
    };

    return thing;
}

int main(int argc, const char* argv[]) {
    struct t_thing thing = retArr();
    ...
    return 0;
}

The typical problem you face is that int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; in your example refers to memory which is reclaimed after the function returns. That means it is not safe for your caller to read (Undefined Behaviour).

Other approaches involve passing the array (which the caller owns) as a parameter to the function, or creating a new allocation (e.g. using malloc). The struct is nice because it can eliminate many pitfalls, but it's not ideal for every scenario. You would avoid using a struct by value when the size of the struct is not constant or very large.

Sign up to request clarification or add additional context in comments.

2 Comments

What do you use when the array is large? For instance I need double array of 44k x 2.
@sAguinaga consider passing a reference to a structure or array by parameter, rather than returning a value. a large value, as you have probably guessed, is capable of exhausting the (remaining) stack storage. in some cases, one might choose to return a heap-allocated structure or array.
4

We can solve it by using Heap memory / memory allocating using stdlib :

Allocating memory using stdlib can be done by malloc and calloc.

creating array:

  • int  ** arr=( int * * ) malloc ( sizeof ( int * ) * 5 ); 
    
    is for allocating 5 rows.
  • arr[i]=(int *)malloc(sizeof(int)*5);
    
    is for allocating 5 columns in each "i" row.
  • Thus we created arr [ 5 ] [ 5 ].

returning array:

  • return arr;
    

We just need to send that pointer which is responsible for accessing that array like above.

#include<stdio.h>
#include<stdlib.h>
int **return_arr()
{
    int **arr=(int **)malloc(sizeof(int *)*5);
    int i,j;
    for(i=0;i<5;i++)//checking purpose
    {
        arr[i]=(int *)malloc(sizeof(int)*5);
        for(j=0;j<5;j++)
        {
            arr[i][j]=i*10+j;
        }
    }
    return arr;
}
int main()
{
    int **now;
    now=return_arr();
    int i,j;
    for(i=0;i<5;i++)
    {
        for(j=0;j<5;j++)
        {
            printf("%d ",now[i][j]);
        }
        printf("\n");
    }
    return 0;
}

1 Comment

Don't cast the result of malloc in C.
2

Several issues:

First of all, you cannot initialize an array from a function call; the language definition simply doesn't allow for it. An array of char may be initialized with a string literal, such as

char foo[] = "This is a test";

an array of wchar_t, char16_t, or char32_t may be initialized with a wide string literal, but otherwise the initializer must be a brace-enclosed list of values.

Secondly, you have a type mismatch; except when it is the operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted to an expression of type "pointer to T", and the value of the expression will be the address of the first element;

In the function retArr, the type of a in the expression is "3-element array of 3-element array of int"; by the rule above, this will be converted to an expression of type "pointer to 3-element array of int", or int (*)[3]:

int (*retArr())[3]
{
  int a[3][3] = ...;
  return a;
}

but as Brendan points out, once retArr exits a no longer exists; the pointer value that is returned winds up being invalid.

Comments

-1
#include <stdio.h>

int** retArr()
{
    static int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
    return a;
}

int main()
{
    int** a = retArr();
    return 0;
}

You could also specify the returned variable as static. You also must declare the variable a in main as just int** (and not specify the dimensions).

1 Comment

The function returns a pointer to a region of memory that contains 9 int's. Pretending that it contains a pointer to int is grossly incorrect and will give you nothing but headaches.
-1

In the example given by the OP, it is the easiest to put the array on the stack. I didn't test this but it would be like this.

#include stdio.h

void retArr(a[][3]) {
  a[0][0] = 1; a[0][1] = 2; a[0][2] = 3;
  a[1][0] = 4; a[1][1] = 5; a[1][2] = 6;
  a[2][0] = 7; a[2][1] = 8; a[2][2] = 9;
}

main() {
  int a[3][3];
  retArr(a);
}

Yeah, this doesn't "return" the array with the return function, but I would suppose that wasn't the intent of the question. The array, a[][], does get loaded, and the loaded a[][] is available in main after retArr() is called, nothing is overwritten.

Comments

-2

For this:

int * retArr() {
    int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
    return a;
}

The array has local scope and is destroyed as soon as you exit the function. This means that return a; actually returns a dangling pointer.

To fix this, put the array in global scope, or use malloc() and copy the array into the allocated space.

Comments

-5

Needs to return int**, not int.

4 Comments

Wrong for at least two reasons; the return type would be int (*)[3], not int **, and the array ceases to exist when the function returns, so the pointer value is invalid.
@JohnBode: int ** isn't wrong, it's just less strongly typed. (But returning a pointer to a stack variable is definitely wrong.)
Well, that's why I posted asking what kind of error he is getting. I spotted the compile error; leaving my answer as it is valid. I would also say it's better to deal with pointers than arrays in function signatures but I will expand this tomorrow
Returning a pointer to a region of memory that contains 9 int's and pretending that it contains a pointer to int is grossly incorrect.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.