Reputation:
I've heard quite a bit about this line: void typedef name
.
Compiles well:
void typedef name;
int main(){}
What does void
even mean? Doesn't it just mean that something is just void? How can it be used before a keyword like typedef
? Isn't it invalid use of void
? It seems to be the same as doing:
typedef void name;
And makes name
an alias for void
.
Does the compiler rearrange typedef
and void
?
I thought void
is only usable with functions:
void func();
But for what things can void
be used and what does it mean? And how does void typedef name
work even though it's not a function declaration?
Upvotes: 3
Views: 179
Reputation: 224546
In C, a declaration is one or more declaration-specifiers followed by a list of declarators with optional initializers. Humans tend to write the specifiers in a particular order, but the C grammar allows them to be written in any order. They are:
typedef
, extern
, static
, _Thread_local
, auto
, and register
.void
, char
, short
, int
, long
, float
, double
, signed
, unsigned
, _Bool
, _Complex
, _Atomic (type-name)
, and structure specifiers, union specifiers, enum specifiers, and (previously defined) typedef names.const
, restrict
, volatile
, and _Atomic
.inline
and _Noreturn
._Alignas (type-name)
and _Alignas (constant-expression)
.There are some rules about how many times various specifiers may appear and rules about which may appear with which. However, there is no rule about the order in which they appear. So all of the above can be rearranged as desired. That includes putting some of the specifiers in between the type-specifiers that we normally group together, such as const long static int _Alignas (double) long signed x;
, which contains signed long long int
in a confusing way. The compiler does not care; it remembers everything and figures it out.
So void typedef name
is the same as typedef void name
; it defines name
to be an alias for void
.
As you can see from the list above, void
is a type-specifier. Quite simply, it specifies a type. That type is defined to be incomplete, meaning it has no defined size. Further, the C standard specifies it cannot be completed; no size can be given to it. The fact that it has no size serves to prevent programs from accidentally referring to void
objects: If p
is a void *
, then *p
would refer to a void
object, and, if a program actually attempts to access it, the compiler should issue a diagnostic message.
The declarators in a declaration are the things built around identifiers being declared:
[
and ]
to indicate an array, with various options for inside the brackets.(
and )
to indicate a function, with various options for inside the parentheses.*
to indicate a pointer, optionally with type-qualifiers (like const
) between the *
and the declarator.Upvotes: 2
Reputation:
typedef
is by syntax a storage class specifier, of which there can only be one in the declaration specifiers (except _Thread_local).
The order of declaration spcifiers (the "T", not the "D" part of a declaration) is free - most put const char
and not char const
. But e.g. char const*const x
is also used.
Semantically, typedef
creates "only" a synonym for the given type. So yes, the compiler does rearrange (parses that declaration)
While a void x;
declaration gives an error, it compiles with a typedef
. Depends how you use it later e.g. for a pointer:
typedef void _0;
_0 *y;
Even though _0* y
is the same, the position of the *
can not be switched. It is on the left of the declarator ("D") giving T*D
with all white-space variations.
Upvotes: 3