Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it actually true that when function prototype has a parameter declared as int a[][10] the compiler treats it as int (*a)[10]?

Tags:

arrays

c

I have heard many people saying that when we want to pass a 1D array to a function fun the following prototypes are equivalent:

1.

   int fun(int a[]);
   int fun(int a[10]);
   int fun(int *a);

I have even heard people say that the 1st and 2nd one are internally converted to the 3rd one in C. I guess that this is true because doing something as sizeof(a) in the definition of the function declared in 2 gives the size of a pointer in bytes (and not 10*sizeof(int)).

Now that being said, I have seen texts claiming that to pass a 2D array to a function the following are equivalent:

1.

int fun(int a[][10]);
int fun(int (*a)[10]);

And here again I have heard people say that in C the 1st one is internally converted to the second one. If that is true, the following should have been equivalent right?

1.

int fun(int a[][]);
int fun(int (*a)[]);

But unfortunately the first one puts forth a compilation error but the second one does not:

    1 | int fun(int a[][]);
      |             ^
t.c:2:13: note: declaration of ‘a’ as multidimensional array must have bounds for all dimensions except the first

This makes me feel that C is treating a in the first as a multidimensional array each of whose element is an integer array but their type is not complete (int[] namely).

While in the second one, a is just a pointer to an array of integers (with size not specified or incomplete type). And the two are indeed different and one format is not equivalent to the other...

Can anyone guide me in details as to what actually happens in C, in each of these cases?

like image 910
Abhishek Ghosh Avatar asked Dec 23 '21 10:12

Abhishek Ghosh


People also ask

What is the return type of the function with prototype?

The return type is "void". This means that the function is not going to return any value. Note that the parameter names in the first example are optional.

What is a function prototype why do you use it?

A function prototype is a definition that is used to perform type checking on function calls when the EGL system code does not have access to the function itself. A function prototype begins with the keyword function, then lists the function name, its parameters (if any), and return value (if any).

Is function prototype necessary in C?

It is not required, but it is bad practice not to use prototypes. With prototypes, the compiler can verify you are calling the function correctly (using the right number and type of parameters).


Video Answer


2 Answers

First, the rules for declarations say that the element type of an array must be complete, per C 2018 6.7.6.2 1. So int a[][] gets a compiler error since the first [] specifies an array whose elements would be int [], which is incomplete.

After the declaration is analyzed, a declaration of a function parameter to be an array is adjusted to be a pointer, per C 2018 6.7.6.3 7.

int (*a)[] is allowed with no error because there is no rule that a pointer must point to a complete type. (If arithmetic is performed on the pointer, then the pointed-to type must be complete, per C 2018 6.5.6 2 and 3.)

like image 189
Eric Postpischil Avatar answered Oct 19 '22 18:10

Eric Postpischil


The relevant rule is found in C17 6.7.6.3/7:

A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation

This is sometimes informally referred to as "array decay" and is similar to the rule where an array identifier is used in an expression.


I have even heard people say that the 1st and 2nd one are internally converted to the 3rd one in C

Yes that is correct, as per the above quoted rule. All 3 declarations in your first example are 100% equivalent.


Now that being said, I have seen texts claiming that to pass a 2D array to a function the following are equivalent: /--/
And here again I have heard people say that in C the 1st one is internally converted to the second one.

Correct.


int fun(int a[][]); is an invalid declaration because this is actually an array of incomplete array types, where all items of each array is an incomplete type of int. C does not allow declarations of arrays with elements of incomplete type.

C17 6.7.6.2/1

The element type shall not be an incomplete or function type.

We can however leave the outermost dimension with incomplete array type since it gets adjusted to a pointer anyway, making its size irrelevant. But that can't be done for the inner dimensions as per the above rule that elements of arrays must be of a complete type. (We can't have arrays of incomplete struct types either.)

int (*a)[] is valid since it's a pointer to an array of incomplete type. Similarly C allows us to use pointers to incomplete struct types, but we cannot declare objects of an incomplete struct type.

like image 30
Lundin Avatar answered Oct 19 '22 20:10

Lundin