Can a pointer to an incomplete type be incomplete?

2020-08-21 02:39发布

问题:

Can int (*)[] be an incomplete type?

C 2018 6.2.5 1 says:

At various points within a translation unit an object type may be incomplete (lacking sufficient information to determine the size of objects of that type) or complete (having sufficient information).

Thus it seems that if the size of a type is known, the type is complete. 6.2.6.1 28 specifies that certain types of pointers must have the same sizes (pointers to void and characters, pointers to compatible types, pointers to structures, and pointers to unions), but pointers to other types may vary.

In a C implementation where all pointers, or all pointers to arrays of int, have the same size, then the size of int (*)[] is known, so it would be complete. In an implementation that, say, uses different pointers for large arrays, the size would not be known, so it is incomplete.

As M.M points out, a structure must not contain a member with incomplete type, except a final flexible array member, per a constraint in 6.7.2.1 3. This suggests that an implementation with one size of pointers must accept struct { int (*p)[]; } while an implementation that has different sizes for such arrays must diagnose a constraint violation. (This in turn means such a declaration is not part of strictly conforming C.)

回答1:

An array of unknown size is incomplete:

An array type of unknown size is an incomplete type. It is completed, for an identifier of that type, by specifying the size in a later declaration (with internal or external linkage).

The type int (*)[] however is not incomplete: It's a pointer of an array of int of unknown size.
And a pointer has a well known size:

printf ("Size %d\n", sizeof(int (*)[]));

6.2.5/23: A type has known constant size if the type is not incomplete and is not a variable length array type.

Furthermore you can even dereference it, thanks to the array semantics:

typedef int (*T)[];
...
int a[10];
for (int i=0; i<10; i++) a[i]=i;
T p=a;
for (int i=0; i<10; i++) printf ("%d ",(*p)[i]);
printf ("\n");

Edit

In addition, a pointer is always a complete type. It's written black on white in 6.2.5/20:

A pointer type may be derived from a function type or an object type, called the referenced type. A pointer type describes an object whose value provides a reference to an entity of the referenced type. A pointer type derived from the referenced type T is sometimes called ‘‘pointer to T’’. The construction of a pointer type from a referenced type is called ‘‘pointer type derivation’’. A pointer type is a complete object type.