1

The following statement declares a function which takes no argument and returns a pointer to an integer array.

int (*f())[];

It returns a pointer to an integer array of size _____
We didn't specify the size of the array, so it should give some kind of warning or error.

I am asking this because when we pass a 2-D array or a pointer to an integer array to a function, we are always supposed to specify the dimension while declaring the pointer in the formal arguments.
So, Why is this declaration allowed?
Is there any specific reason for not throwing an error or warning for this kind of declaration?
Is it that we can also omit the dimension while defining this function OR it becomes inevitable to specify the dimension while defining it?
For a better understanding, Please give a dummy definition of this function as well.

Vinay Yadav
  • 1,206
  • 1
  • 10
  • 19
  • You can't return an array from a function. As with a parameter, if you use an array as a return type it decays to a pointer. – rici Aug 27 '20 at 15:43
  • Arrays don't have any context through a function call in C... they decompose into a pointer... basically it just passes in the pointer to the first element no matter how big it is. – Grady Player Aug 27 '20 at 15:43
  • 3
    By the way, `f()` does not declare a function which takes no arguments. That would be `f(void)`. `f()` declares a function without making any declaration of its arguments, which makes it your responsibility to call the function correctly. – rici Aug 27 '20 at 15:45

3 Answers3

2

Throw it into cdecl and you'll see:

int (*f())[];

declare f as function returning pointer to array of int

This happens because of array to pointer decay.

Thomas
  • 174,939
  • 50
  • 355
  • 478
  • What has the array to pointer decay to do with this declaration? – RobertS supports Monica Cellio Aug 27 '20 at 15:58
  • @RobertSsupportsMonicaCellio Quoting from the link that quotes from the Standard: "an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue." Hm, yeah, this isn't an _expression_. Please edit or post a better answer if you have one! – Thomas Aug 27 '20 at 16:00
  • What I mean is the array to pointer decay AFAIK has nothing to with the declaration of `f`. `f` just returns a pointer to an array of unknown elements of `int`. That's it. No decay involved in here. – RobertS supports Monica Cellio Aug 27 '20 at 16:01
1
int (*f())[];

fine

int (*f())[][];

error

int (*f())[][8];

fine

When you pass or return an array, you must give all dimensions other than the first one. The working definition.

Example implementation:

int (*f())[]
{
    static int array[8];
    static int *aptr = array;
    return &aptr;
}

You might do something like this for lazy initialization (including lazy allocation) which is its own topic.

Joshua
  • 40,822
  • 8
  • 72
  • 132
  • Sir, in the example implementation Why did you store the address in an int variable named aptr. the array represents a pointer to an int and you are storing it in another int variable and returning that variable's address but we are supposed to return a pointer to an integer array not a pointer to an integer which is pointing to an int – Vinay Yadav Aug 29 '20 at 01:13
  • @VinayYadav: Because I needed something that was of type "pointer to array of int"; and `&array` isn't that. – Joshua Aug 29 '20 at 01:25
  • So, Why didn't you make a 2-D array and return its name because the name is nothing but a pointer to the 0th 1-D array. What you are returning is not a pointer to an array of int. It is pointer to pointer to 0th int element of array – Vinay Yadav Aug 29 '20 at 01:30
0

"We didn't specify the size of the array, so it should give some kind of warning or error."

We don't need to specify the size of the array to point to. To know the exact size of the array to point to in the caller is not required. f just returns a pointer, not an array.

"I am asking this because when we pass a 2-D array or a pointer to an integer array to a function, we are always supposed to specify the dimension while declaring the pointer in the formal arguments."

No, that's not true. If you pass a pointer to an array as argument to a function, it doesn't matter if you declare the parameter to be a pointer to an array of 10 or 50 elements or even not to point to an array and just declare a single pointer.

int f (int *p)
{
    return *p;
}

int a[7];
int b = f(a);

is perfectly valid.

int* p is equal to int p[] as well as equal to int p[239].

The pointer passed is treated as single pointer.

In case of passing pointers to 2D arrays (or more specific a pointer to an array of int) in the caller, the first can be omitted but last dimension need to be specified.

int f (int (*p)[5])
{
    return **p;
}

int a[4][5];
int b = f(a);
  • In the second example, We are not passing a pointer to 2D arrays instead we are passing a pointer to an integer array. – Vinay Yadav Aug 28 '20 at 01:40
  • @VinayYadav I just said that to clarify the context. Yes, in this example, we are passing a pointer to an array of 5 `int`. – RobertS supports Monica Cellio Aug 28 '20 at 08:54
  • that was my question actually, it doesn't clear any context. Why did you write that's not quite true? It is true – Vinay Yadav Aug 28 '20 at 10:09
  • @VinayYadav Both examples show that "*we are always supposed to specify the dimension while declaring the pointer in the formal arguments.*" is not true. In the first example, no dimension is needed. In the latter, the size of the array the pointer point to can be omitted too. In both cases you don't need to specify the size of the array to point to at all. – RobertS supports Monica Cellio Aug 28 '20 at 10:14
  • See this: https://ide.geeksforgeeks.org/bc3Ma5RHcv It gives error when I am not specifying the size in second case – Vinay Yadav Aug 29 '20 at 00:59
  • @VinayYadav Yes, but this dimension belongs to the last dimension and not the first dimension. F.e. the `[3]` in `int (*p)[3]` belongs to `a[3][here]`, not `a[here][3]`. So as equal to the first example the first dimension can be omitted. `int (*p)[3]` is a pointer to the first element of the first array of arrays in `a`, and not a pointer to an array of arrays. The difference at the dimension matters. – RobertS supports Monica Cellio Aug 29 '20 at 07:32