In the library FreeImagePlus, in FreeImage.h
, there is a funny #define
which seems to create a typedef
and an enum
with the same name:
#define FI_ENUM(x) typedef int x; enum x
This is expanded by the preprocessor to code like:
typedef int FREE_IMAGE_FILTER;
enum FREE_IMAGE_FILTER {
FILTER_BOX = 0,
FILTER_BICUBIC = 1,
[...]
What does this do? Is it even legal to have a typedef
and an enum
with the same name?
And isn't an enum
compatible to int
anyway? Why does FreeImage do this?
Names of structures, unions and enumerations lives in their own namespace. That's why you can declare a struct
/union
/enum
variable with the same name as the actual struct
/union
/enum
.
And it's not the name of the complete enum
(e.g. for enum X
I mean the X
) that has to be compatible with an integer, it's the names inside the enumeration.
Quoting C99 N1256 draft 6.2.1 "Scopes of identifiers":
An identifier can denote an object; a function; a tag or a member of a structure, union, or enumeration; a typedef name; a label name; a macro name; or a macro parameter.
which means that in:
typedef int id;
id
is an identifier.
And from 6.2.3 "Name spaces of identifiers":
BEGIN QUOTE
If more than one declaration of a particular identifier is visible at any point in a translation unit, the syntactic context disambiguates uses that refer to different entities. Thus, there are separate name spaces for various categories of identifiers, as follows:
- label names (disambiguated by the syntax of the label declaration and use);
- the tags of structures, unions, and enumerations (disambiguated by following any of the keywords struct, union, or enum);
- the members of structures or unions; each structure or union has a separate name space for its members (disambiguated by the type of the expression used to access the member via the . or -> operator);
- all other identifiers, called ordinary identifiers (declared in ordinary declarators or as enumeration constants).
END QUOTE
So in:
typedef int id;
enum id {ID0};
- the first
id
is an ordinary identifier - the second is a tag identifier
an both can coexist pacifically.
On the other hand, we could not do something like:
typedef int id;
int id;
because both would be ordinary identifiers.
来源:https://stackoverflow.com/questions/17918380/typedef-and-enum-with-same-name