سؤال

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.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top