Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I complete a typedef name of array type?

The C standard states (§6.2.5 p22):

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

And it works fine as far as variable declarations are concerned:

int a[];
int a[2]; //OK

But when we add typedef before those declarations the compiler complains (I also changed the name):

typedef int t[];
typedef int t[2]; //redefinition with different type

It doesn't complain however when we are completing a typedef to incomplete structure instead:

typedef struct t t1;
typedef struct t { int m; } t1; //OK

Possible use case of an incomplete typedef of array could be something like this:

int main(int n, char **pp)
{
    typedef int t1[][200];
    typedef struct t { t1 *m; int m1; } t0;
    typedef int t1[sizeof (t0)][200];
}

In the above example I would like to declare a pointer to array inside a structure with number of elements equal to the structure size. Yes I could use a structure instead of array but why should I when the above option is potentially available?

like image 928
AnArrayOfFunctions Avatar asked Feb 13 '17 02:02

AnArrayOfFunctions


1 Answers

typedef int t[2]; is not allowed because of the constraint 6.7/3:

If an identifier has no linkage, there shall be no more than one declaration of the identifier (in a declarator or type specifier) with the same scope and in the same name space, except that:

  • a typedef name may be redefined to denote the same type as it currently does, provided that type is not a variably modified type;

However int[] and int[2] are not the same type, so this "except" doesn't apply, and so the code violates the constraint.


Regarding your first quote: Although 6.2.5/22 says that an incomplete type can be completed, it doesn't follow that any attempted completion is automatically legal. The attempted completion must also comply with all the other rules of the language, and in this case it does not comply with 6.7/3.

The int a[]; int a[2]; example is OK (under 6.7/3) because a has linkage; and in the typedef struct t t1; , struct t is still the same type before and after its completion.

like image 171
M.M Avatar answered Oct 13 '22 23:10

M.M