0

A function dynamically creates an int array whose elements are predetermined to be int[2]. Is there any way to have a function assign values to that array and then return it to the caller.

The below code accomplishes this task but throws warning: initialization from incompatible pointer type [enabled by default]

#include <stdlib.h>
#include <stdio.h>

int *get_values()
{
    int (*x)[2] = malloc(sizeof(int[2])*3);

    x[0][0] = 1;
    x[0][1] = 2;

    x[1][0] = 11;
    x[1][1] = 12;

    x[2][0] = 21;
    x[2][1] = 22;

    return x;   
}

int main()
{
    int (*x)[2] = get_values();

    int i;
    for (i=0; i!=3; i++)
        printf("x[%d] = { %d, %d }\n", i, x[i][0], x[i][1]);
}

I'm aware of the alternative where you dynamically allocate both dimensions, but this is something that I am curious about.

4
  • 1
    Why don't you declare the correct function return type? Commented Apr 6, 2016 at 11:41
  • 2
    @PeterA.Schneider Maybe because he doesn't know how to put it in the prototype ;) The correct prototype for your function should be int (*get_values())[2] { ... }. Commented Apr 6, 2016 at 11:46
  • I wasn't quite sure either and wanted to check first. But "how do I declare..." was not what the OP asked ;-). Commented Apr 6, 2016 at 11:52
  • Btw, I think it's fine to simply cast the pointers around as needed. Commented Apr 6, 2016 at 11:56

2 Answers 2

7

Rather than keep repeating the same clunky syntax it can be helpful to define a typedef in cases like this. This makes it easier to declare the correct return type for get_values:

#include <stdlib.h>
#include <stdio.h>

typedef int I2[2];

I2 * get_values(void)
{
    I2 * x = malloc(sizeof(I2) * 3);

    x[0][0] = 1;
    x[0][1] = 2;

    x[1][0] = 11;
    x[1][1] = 12;

    x[2][0] = 21;
    x[2][1] = 22;

    return x;   
}

int main()
{
    I2 * x = get_values();

    int i;
    for (i=0; i!=3; i++)
        printf("x[%d] = { %d, %d }\n", i, x[i][0], x[i][1]);

    free(x);
}

LIVE DEMO

Recommended reading: Don't repeat yourself (DRY).

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

Comments

4

And this is how it looks without a typedef:

int (*get_values(void))[2]
{  
    return NULL;   
}

Pretty unreadable.

Notice in that function definition, if you replace get_values(void) with x you get: int (*x)[2], which is exactly what the pointer definition looks like.

13 Comments

@2501 But it compiles for me without any warnings when omitting the 2 (GCC).
@CoolGuy Apparently in this case you can omit the 2, however if the returned type doesn't match with the assigned type, the behavior is undefined. Omitting the size also removes warnings that will warn you about the type discrepancy. In any case, there is no good reason to omit it, even you if are allowed to.
@2501 Yeah int(*get_values((int*)[2]))[2] is totally trivial reading :)
@CoolGuy I'm wondering what meaning gcc bestows on int (*get_values(void))[]. In particular, what value it thinks get_values()+1 should have then.
@PeterA.Schneider It is a pointer to an incomplete type. It can't be dereferenced. I'm not sure if int(*)[] is compatible with int(*)[2], but gcc thinks it is.
|

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.