26

In this SO question I've encountered a very weird typedef:

struct Date { int day, month, year; } typedef date_s; 

I've always been seeing typedefs following this 'rule':

typedef <existing> <new>; 

For example:

typedef unsigned long long ull; typedef int kph; // speed typedef void (*alpm_cb_log)(alpm_loglevel_t, const char *, va_list); typedef int int_t; typedef char char_t, *char_p, (*fp)(void); 

The 4th one is taken from here, the 5th and 6th are from cppreference


And this is how I would typedef a struct:

typedef struct { int a, b, c; } data; // and then use it data Something; 

The question is how is this even possible to write such a typedef? It doesn't even make sense (at least to me).

clang doesn't give any errors or warnings, even with -Wall -Wextra.

Bonus question: should I advise the author of the question where this code could be found to avoid using such a typedef (because it's very unusual and may lead to confusion)?

3
  • 5
    It is fine, though unusual. Much as int const i; Commented May 1, 2016 at 20:33
  • 4
    @piling I like int const i much more than const int i. It's less confusing when working with pointers, since you only have to follow one general rule: "Whatever precedes const is const". int const* i; is much more concise than const int *i;. Commented May 1, 2016 at 20:43
  • The actual rule is that it is the same as declaring a variable, but putting typedef (almost) anywhere makes it declaring a type alias instead of a variable. People usually put it at the front for clarity Commented May 1, 2016 at 21:04

1 Answer 1

31

It turns out that typedef can be placed after the existing type (in addition to before it). This little oddity, now obsolescent*, is caused by the way in which the C standard "bundles" typedefs with storage class specifiers, such as static and auto:

A declaration is defined as follows:

<declaration> ::= {<declaration-specifier>}+ {<init-declarator>}* 

This means that declaration specifiers can appear in any order. Now, declaration specifier is

<declaration-specifier> ::= <storage-class-specifier> | <type-specifier> | <type-qualifier> 

And storage class specifier is

<storage-class-specifier> ::= auto | register | static | extern | typedef 

The declaration of the struct's elements is a type specifier. Like typedef keyword, it is a declaration specifier. Since declaration specifiers can appear in any order, both placements of typedef (i.e., before and after the struct) are valid and identical to each other.

* N1570, 6.11.5: "The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature." Thanks, Keith Thompson, for a great comment!

Sign up to request clarification or add additional context in comments.

1 Comment

N1570 6.11.5: "The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature." It's still perfectly legal, but a future version of the language might make it illegal.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.