0

EDIT: the correct syntax for declaring a function with the return type of array pointer in the example I wrote further below in my code example section should be as follows:

int (*my_function(void))[10]
{
    ...
}

Important note for future readers who might come across the same question: don't typecast malloc! Just don't. Thanks to user3386109 for that one. Further reading on the why.

Thanks to Andrew Henle and Eric Postpischil for their answers. Here's a really good explanation if anyone wants to read further on the the topic. Original thread below:

What I want to know

How to return a pointer to array in C.

Why I want to know that

Because it (is?) should be possible to do so.

For what I want it

To return multidimensional arrays from functions.

"Have you tried structs?"

Yes, but this isn't about structs. The point (no pun intended) of this thread is doing it with pointers.

Code example

My example is wrong, thus the reason I'm asking here, but here it go:

int (*)[10]my_function(void) // Should be returning a type of array pointer to 10-elements array. Sure enough it's not.
{
    int (*ptr)[10] = (int (*)[10]) malloc(10 * sizeof(int));
    return ptr;
}

int main(void)
{
    printf("Address of ptr is: %d", my_function());
    return 0;
}

As you can see, I'm not sure about how to typecast malloc to type array pointer to 10-elements array as well. If you know how, please let me know.

IMPORTANT NOTE

As far as I know, using double pointers (pointer to pointer) in this case is wrong. Code example:

int **my_function(void); // WRONG, afaik

Rationale: this video, at 16:22.

I already tried searching online and in some books, they have examples using structs, pointer to array as function arguments, but not this.

If you have some knowledge about this topic, please reply, I'll be grateful.

donjuardo
  • 13
  • 1
  • 3
  • *"I'm not sure about how to typecast malloc"*. Simple. Don't. [You should not cast the return value from malloc](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – user3386109 Nov 15 '19 at 00:50
  • If you did do `typedef int tenIntArray[10];`, how many plain `int` elements from the start of the array would you expect `tenIntArray *example = ...`; and then `example[ 2 ]` to be? Hint: it's not the third `int` element... – Andrew Henle Nov 15 '19 at 00:50
  • @user3386109 Thank you, I didn't know that. In the tutorial series on pointers I linked to, the instructor says to typecast malloc, so I just assumed it was the right thing. – donjuardo Nov 15 '19 at 01:08
  • @ward0 I haven't watched the video, but if the instructor was using MSVC, note that MSVC is really a C++ compiler with limited support for current standard C - it's not a compliant C compiler outside of 30-year-old C89. – Andrew Henle Nov 15 '19 at 01:11
  • @Andrew Henle He was indeed using MSVC, that might be it. – donjuardo Nov 15 '19 at 01:24
  • For the rare case where you actually need to return array pointers, it is better to pass them as parameters. In your case `void func (int (**arr)[10]) { *arr = malloc ...` This is slightly more readable than returning an array pointer (but still quite ugly). – Lundin Nov 15 '19 at 07:42

2 Answers2

3

Arrays can't be passed by value, unless you embed them in a structure. When you pass an array to or from a function, it decays to a pointer to the first element. So the way to return a dynamically-allocated array is as a single pointer.

int *my_function(void) {
    int *ptr = malloc(10 * sizeof(int));
    return ptr;
}

There's no need to specify the dimension in the type, as this will be ignored.

This is not a multi-dimensional array, it's just a 1-d array of 10 int.

The type declaration int (*ptr)[10] is for an array of 10 pointers to integers, not a pointer to an array of 10 integers.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • *There's no need to specify the dimension in the type, as this will be ignored.* That's probably a bit strong. The certainly won't be ignored if the pointer is assigned to a pointer that's actually a pointer to an array, such as `typedef int arrayType[10];`. In that case, dereferencing the pointer might not produce the desired result. – Andrew Henle Nov 15 '19 at 00:54
  • 1
    You can't assign to an array. Does making it a typedef change that? – Barmar Nov 15 '19 at 01:00
  • 1
    Thanks for the reply. I think you misunderstood my question, and I'm to blame for that. You can *point* to a 1D array using a pointer, this way you can pass the array around from functions and to functions (as yourself said, arrays are always passed by reference). What I want to know is the syntax for creating a pointer of the **type** pointer to array, in order to pass ***multidimensional*** arrays around (returning from functions and passing to functions). – donjuardo Nov 15 '19 at 01:05
  • *You can't assign to an array* True, among other differences. Hence my "might not produce the desired result" comment. I'd personally never `typedef` an array unless for some reason I wanted to then immediately `typedef` a pointer that array for some crazy reason. – Andrew Henle Nov 15 '19 at 01:06
  • @ward0 *What I want to know is the syntax for creating a pointer of the type pointer to array, in order to pass multidimensional arrays around* Read this: [**Correctly allocating multi-dimensional arrays**](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays) – Andrew Henle Nov 15 '19 at 01:08
  • @Andrew Henle Thanks! That helped a lot to clarify the topic – donjuardo Nov 15 '19 at 01:34
2

int (*p)[10] declares a pointer to an array of 10 int.

int (*)[10] is a type that is a pointer to an array of 10 int. However, note that you do not need to cast the result of malloc in C. As a void * used as an initializer or right operand of assignment, it will be automatically converted to the target type.

int (*foo(void))[10] declares a function taking no parameters that returns a pointer to an array of 10 int.

Note that int (*foo(void))[10] can be derived from int (*p)[10] simply by replacing p with foo(void). Generally, to get any return type for a function, write a declaration for an object of that type, then replace the object name with the function name followed by its usual parameter declarations.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Thank you so much, that answers my question. I came to lightly *thought* about using ```int (*foo(void))[10]```, but the [10] in front of the function seemed unnatural to me (kinda looks like declaring an array of functions lol), so I immediately discarded the possibility. Thanks again! – donjuardo Nov 15 '19 at 01:30