user16107274
user16107274

Reputation:

What does void actually mean? How is it usable in this weird way?

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

Answers (2)

Eric Postpischil
Eric Postpischil

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:

  • storage-class-specifier: typedef, extern, static, _Thread_local, auto, and register.
  • type-specifier: 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.
  • type-qualifier: const, restrict, volatile, and _Atomic.
  • function-specifier: inline and _Noreturn.
  • alignment-specifier: _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.

Supplementary Note

The declarators in a declaration are the things built around identifiers being declared:

  • A plain identifier.
  • A declarator followed brackets [ and ] to indicate an array, with various options for inside the brackets.
  • A declarator followed by parentheses ( and ) to indicate a function, with various options for inside the parentheses.
  • A declarator preceded by * to indicate a pointer, optionally with type-qualifiers (like const) between the * and the declarator.
  • A declarator inside parentheses, to override the default grouping in complicated declarators mixing pointers and arrays and such.

Upvotes: 2

user16057579
user16057579

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

Related Questions