Domanda

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?

È stato utile?

Soluzione

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.

Altri suggerimenti

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top