This may be a bad question as I'm really new to the concept of statically-typed language and arrays in C and may have misunderstood these concepts...
I know that C is a statically-typed language, in my understanding, this implies that all types must be known at compile-time.
Also, I know that the number of elements in an array is part of the array's type, and thus the dimension must be known at compile time.
int a = 10;
int arr[a]; // error
However, I noticed that we could have:
int (*p)[];
void fun(int(&r)[]) { }
Why can p
and r
not specify the size of the array?
My humble guess is that, for the above cases, the type of p
is just int(*)[]
and the type of r
is just int(&)[]
, that is, for pointer/reference to array, it is allowed to have type which does not include the size of the array. (At first I was tending to think of p
and r
being in some kind of state where their types are to be "completed" later, but then I realized that if so, C would not be statically-typed)
My I ask if my guess is correct?
It seems really quirky to me, since we can do (in C 20
):
int a[10];
int b[100];
p = &a;
p = &b;
fun(a);
fun(b);
Why would C allow such types (and conversion from the types with array size to them)? When are these "incomplete" type useful?
CodePudding user response:
Everything you said is correct.
In addition to the regular array types T[N]
there are "arrays of unknown bound" T[]
.
Those types are "incomplete", meaning objects of those types can't be created, sizeof()
can't be applied to them, etc. Attempting to create an array of unknown bound requires you to provide an initializer, and transforms the type into a regular array, based on the number of elements in the initializer.
References and pointers to arrays of unknown bound are allowed to point to regular arrays (and that's the only thing they could point to). This is a C 20 change.
Those are indeed quirky. It's not immediately clear to me why they would be useful. They allow you to have a function that accepts a reference/pointer to any "array of T" without adding the array size as a template parameter, and without also accepting "pointers to T".
CodePudding user response:
Yes these are legal types explicitly allowed by the C standard. Such types are useful in about the same circumstances where bare pointers that point to array elements are useful. In both cases, there is an array, but the type of the pointer/reference does not reflect the size of the array. Here are two silly examples:
// use a pointer to an array element
int sum(int* array, int size) {
int ret = 0;
for (int i = 0; i < size; i) {
ret = array[i];
}
return ret;
}
// use a reference to an array
int sum(int (&array)[], int size) {
int ret = 0;
for (int i = 0; i < size; i) {
ret = array[i];
}
return ret;
}