recently I found typedef
in my code works really different than what I proposed. An example like this:
typedef int *ptype;
ptype v1 = 0, v2 = 0;
The result: both v1 and v2 were defined as a pointer to int
type. But if you simply replace ptype
by int *
in the second sentence as int *v1 = 0, v2 = 0;
or int* v1 = 0, v2 =0;
, only v1 will be the pointer and v2 is normal int
. It seems typedef
does not do a simple replacement. What's more, when it comes to complicate modifier like:
typedef int *ptype;
const ptype v3 = 0;
The result will be: v3 is a const
pointer, not a pointer to the const
int if we write const int *v3 = 0;
. In the above code const
stands as the modifier to the whole ptype
, not the int
inside ptype
. Thus it really looks like typedef
combines the compound type int*
and creates a new type.
However, the authoritative C/C++ reference website cplusplus says "typedef does not create different types. It only creates synonyms of existing types." so I was really confused and hope someone can help explain the behavior of typedef
. Thanks!
"Synonym" does not mean "text replacement". ptype
is not literally expanded to int *
by the preprocessor or anything.
What it means is that you can do things like:
typedef int *ptype;
ptype a;
int *b;
a = b; // OK
The assignment is valid because ptype
and int *
are the same type; there is no type conversion or cast required.
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").
In other words, the new names created by typedef
behave like built-in keywords as far as declaring things goes, but the actual types represented by those names are the same.
When cplusplus.com says that typedef
doesn't create a new type, what they mean is that anywhere where you can use a value of ptype
you can also use a value of type int*
and vice-verse. So if you define a function that takes a ptype
parameter, you can pass it an int*
without any conversions being necessary.
That does not mean that a typedef
is implemented as purely textual substitution like a #define
would be.
Referring to C89, section 3.5, here's the reason that ptype v1 = 0, v2 = 0;
is not equivalent to int *v1 = 0, v2 = 0;
. Later versions of C and C++ were informed by C89 and are essentially the same in this respect.
In ptype v1 = 0, v2 = 0;
, ptype
is the "declaration-specifiers", and v1 = 0, v2 = 0
is the "init-declarator-list". Specifically, ptype
is a "type-specifier" and even more specifically it's a "typedef-name". So, we're declaring two variables (v1
and v2
) both of which have type ptype
, which is another name for int*
.
In int* v1 = 0, v2 = 0
, int*
is not the "declaration-specifiers", because that consists of a series of "type-specifier", "storage-class-specifier" and "type-qualifier". You can look up each of those in turn, but all put together they amount to a whole list of keywords like static
or const
, built-in type names, plus typedef and enum names and struct/union specifiers. They don't include the *
, which is part of the syntax for a compound type. So in this case int
is the "declaration-specifiers and *v1 = 0, v2 = 0
is the "init-declarator list". Once we break down the grammar of the "init-declarator list", the *
applies only to v1
, not to v2
. That's why it defines one int*
and one int
.
Similarly you could write ptype *v1 = 0, v2 = 0;
, which would define one pytpe*
and one ptype
. That is to say, one int**
and one int*
.
The grammar for const int *
vs const ptype
works out to a similar result -- in the former the const
"type-qualifier" applies to the int
but in the latter it applies to ptype
.
来源:https://stackoverflow.com/questions/14334317/does-typedef-in-c-c-really-create-a-new-type-by-combining-the-compound-type-e