Home > OS >  Is it actually true that when function prototype has a parameter declared as int a[][10] the compile
Is it actually true that when function prototype has a parameter declared as int a[][10] the compile

Time:12-24

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?

CodePudding user response:

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.)

CodePudding user response:

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.

  • Related