is the `synonym` in a `typedef` mandatory?
I encountered this in a code review:
typedef struct C { int i; };
It compiles.
Apart from it being C-style, where structs are in a separate 'namespace', and need to be typedeffed in order to use later on, I found it weird that there is nothing defined with this typedef...
So开发者_高级运维: doesn't typedef
require a type argument and an alias argument?
A quick glance over n3225 doesn't show any requirement that a name is required to be present. The text that comes the most near just says
In a simple-declaration, the optional init-declarator-list can be omitted only when declaring a class (clause 9) or enumeration (7.2), that is, when the decl-specifier-seq contains either a class-specifier, an elaborated- type-specifier with a class-key (9.1), or an enum-specifier.
So your code seems to be valid, but I think it smells bad.
Yes, typedef
requires another argument. That typedef
won't do anything.
Anyway it's not an error, just a deprecate usage of typedef
.
C standard (n1256 in 6.7.7) talks about typedef
. It doesn't say this usage is deprecated, but compilers report it is, since such statement has no effect.
Thank you for testing your code with Comeau C/C++!
Tell others about http://www.comeaucomputing.com/tryitout !
Your Comeau C/C++ test results are as follows:
Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions
"ComeauTest.c", line 1: warning: declaration requires a typedef name
typedef struct C { int i; };
^
You are most likely using very old compiler, which allows you to compile that line. Using g++ 4.3.0 (which is already fairly old), without any additional options, give this :
g++ dfg.cpp
dfg.cpp:2: warning: ‘typedef’ was ignored in this declaration
So, try to compile that using a compiler which is more c++ standard compliant.
Indeed, that's not valid. You're using the keyword typedef
to create an alias, then not specifying what the alias should be!
(Strictly speaking it's deprecated, not invalid. But hey.)
Consider the parallels between:
typedef struct C { int i; };
extern struct P { int i; };
GCC 4.2.1 with no explicit warnings enabled (gcc -c xxx.c
) says of the first:
xxx.c:1: warning: useless storage class specifier in empty declaration
xxx.c:2: warning: useless storage class specifier in empty declaration
Note that they are only warnings; they are not an error because the standard allows the notation, though it does not do very much. In each case, the example simply declares a structure type, which can be used by the name struct C
or struct P
. The storage classes are irrelevant because no object is named. In C++, those declarations also declare types C
and P
(but that would also happen if the typedef
or externwas not there); in C, those types (
Cand
P`) are not declared.
In the C standard, typedef
is treated as a storage class, like extern
and static
are storage classes. That means that the following code is legitimate:
typedef struct C { int i; } name1;
extern struct P { int i; } name2;
It declares the same two structure types as before, but now the typedef
declares an alias for struct C
which is name1
, and the extern
line states that another translation unit (TU) defines a variable called name2
of the type struct P
. Neither is vacuous (except that the definitions are not used later in the 2-line TU shown).
The C standard allows many weird things. For example:
int unsigned typedef u;
It's a perfectly valid - but totally abnormal - way of writing:
typedef unsigned int u;
There is a section in C99 §6.11.5 (under Future Language Directions) which says:
6.11.5 Storage-class specifiers
The placement of a storage-class specifier other than at the beginning of the declaration specifiers in a declaration is an obsolescent feature.
That makes my weird example in violation of §6.11.5.
Summary
- The code reviewed is syntactically correct in C, both C89 and C99.
- It is also, AFAIK, syntactically valid in C++ - but it is even more pointless there than in C since
struct C { int i; };
with no typedef introduces the type C (as well asstruct C
). - The code reviewed should not be accepted - it is reasonable to require it to be fixed.
The correct fix might be to remove the storage class (typedef
), or it might be to introduce a name as an alias for struct C
. Since the code compiles without the alias, it is more likely correct to remove the storage class.
精彩评论