I stumbled upon some code where the typedef
keyword is in between the type and the alias name like in
int typedef INT;
It compiles in gcc and clang (live example). I am not very good in understanding standardese. So my question is: Is this standard conformant? Can I rely on compilers to support it?
typedef is a reserved keyword in the programming languages C and C++. It is used to create an additional name (alias) for another data type, but does not create a new type, except in the obscure case of a qualified typedef of an array type where the typedef qualifiers are transferred to the array element type.
A typedef declaration is a declaration with typedef as the storage class. The declarator becomes a new type. You can use typedef declarations to construct shorter or more meaningful names for types already defined by C or for types that you have declared.
typedef simply lets you give a new name to an existing type. But that name combines every aspect of the existing type into an indivisible entity, such that e.g. ptype a, b; is equivalent to ptype a; ptype b; (and const ptype means "const pointer-to-int" because ptype means "pointer-to-int").
They are largely the same, except that: The alias declaration is compatible with templates, whereas the C style typedef is not.
The typedef
keyword is classified as a storage class specifier in C, though the standard explicitly remarks that that's for convenience in expressing the formal language syntax. It nevertheless follows that typedef
can appear in exactly the same places that any other storage class specifier, such as extern
or static
, can appear. [C2011, 6.7.1/5]
In fact, the syntax allows storage-class specifiers to be intermixed with type specifiers, type qualifiers, and other "declaration specifiers" in declarations. [C2011, 6.7/1, 6.7/6]
Thus, yes, it is valid to put the typedef
keyword after the type name, as in your example.
TL/DR Version
Yes, int typedef INT
is conforming.
James Michener Version
C declaration syntax (C 2011 online draft):
6.7 Declarations
Syntax
1declaration:
declaration-specifiers init-declarator-listopt ;
static_assert-declaration
declaration-specifiers:
storage-class-specifier declaration-specifiersopt
type-specifier declaration-specifiersopt
type-qualifier declaration-specifiersopt
function-specifier declaration-specifiersopt
alignment-specifier declaration-specifiersopt
...
What this says is that in a single declaration you can have a sequence of one or more declaration specifiers, where each declaration specifier can be a storage class specifier (auto
, extern
, static
, typedef
), a type specifier (int
, float
, char
, etc.), a type qualifier (const
, restrict
, volatile
, etc.), a function specifier (inline
), or an alignment specifier.
The order in which various specifiers appear doesn't matter; static const short int x;
may be written as int static short const x
, or int short const static x
, etc. As a matter of practice, most people put the storage class specifier first, then any function or alignment specifiers (if necessary), then any type qualifiers, then type specifiers, so static const short int x
is how most people would write that declaration.
This syntax is what allows us to write types like long double
or long long
or unsigned long int
, etc.
Note that while the syntax allows arbitrary (and arbitrarily long) sequences of type specifiers, there's a semantic rule that only allows a relative few. You can't write short short short short x
, for example, or long long long double y
. Only the following sequences are allowed:
Constraints
2 At least one type specifier shall be given in the declaration specifiers in each declaration, and in the specifier-qualifier list in each struct declaration and type name. Each list of type specifiers shall be one of the following multisets (delimited by commas, when there is more than one multiset per item); the type specifiers may occur in any order, possibly intermixed with the other declaration specifiers.
—void
—char
—signed char
—unsigned char
—short, signed short, short int, or signed short int
—unsigned short, or unsigned short int
—int, signed, or signed int
—unsigned, or unsigned int
—long, signed long, long int, or signed long int
—unsigned long, or unsigned long int
—long long, signed long long, long long int, or
signed long long int
—unsigned long long, or unsigned long long int
—float
—double
—long double
—_Bool
—float _Complex
—double _Complex
—long double _Complex
— atomic type specifier
— struct or union specifier
— enum specifier
— typedef name
Addendum
As Keith points out in the comment below, a future revision of the language may limit storage class specifiers to the beginning of the declaration, so int typedef INT
may not be legal under a future compiler.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With