C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Why redefining enumerators as macros?

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Maxim Yegorushkin
Guest





PostPosted: Tue May 02, 2006 10:06 pm    Post subject: Why redefining enumerators as macros? Reply with quote



Hi,

I could not to make up or google an explanation for this (idiom?) often
seen in system headers:

/* Standard well-defined IP protocols. */
enum
{
IPPROTO_IP = 0, /* Dummy protocol for TCP. */
#define IPPROTO_IP IPPROTO_IP
IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS
IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
#define IPPROTO_ICMP IPPROTO_ICMP
IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
#define IPPROTO_IGMP IPPROTO_IGMP
....

Could anybody shed some light on why they make enumerators preprocessor
macros? To enable for some fancy preprocessing?


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Greg Herlihy
Guest





PostPosted: Wed May 03, 2006 10:06 am    Post subject: Re: Why redefining enumerators as macros? Reply with quote



Maxim Yegorushkin wrote:
Quote:
Hi,

I could not to make up or google an explanation for this (idiom?) often
seen in system headers:

/* Standard well-defined IP protocols. */
enum
{
IPPROTO_IP = 0, /* Dummy protocol for TCP. */
#define IPPROTO_IP IPPROTO_IP
IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS
IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
#define IPPROTO_ICMP IPPROTO_ICMP
IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
#define IPPROTO_IGMP IPPROTO_IGMP
...

Could anybody shed some light on why they make enumerators preprocessor
macros? To enable for some fancy preprocessing?

Even if we are not immediately certain what this code is doing, we can
certainly establish some parameters to guide our inquiry. First, the
fact that this code resides in a system header should leave us with no
doubt as to its purpose. And that purpose is certainly not to do
anything "fancy." (let's stay grounded: this is Unix/Linux/BSD sources
we are looking at here, not boost Smile.

Rather, a bafflingly hideous construct such as this
enum-that-is-also-a-macro (ETIAAM) pattern can only have one
explanation: it exists solely to avert some obscure - but nonetheless -
very real programming disaster. And though we may not yet know what the
exact nature of this potential disaster may be - we can still be
certain that no matter how farfetched or horrific it may sound to us,
the danger that it poses is nonetheless quite real. We can reach this
conclusion because the very existence of this code means that at least
one person (that is, the person who wrote it) was not lucky enough to
have avoided the ordeal.

So with these basic parameters now in place, the mystery that surrounds
this code begins to dissipate. In fact there is little dissipation
needed. I believe that we can readily surmise that the macros for the
enumerated values exist in order to prevent any of the enums being
defined by another macro somewhere else. In other words, there must be
another header file floating around - and one which a client could well
include in their program - that defines its own IPPROTO set of macros -
and defines them with a set of values incompatible with the set of
values used here.

Now that we have reached this logical conclusion, we can appreciate the
full horror of this situation. Imagine what happens when a program
includes this "rogue" header file; the values of the "genuine" IPPROTO
enums silently and invisibly are altered; so that any code in which
they appear - inexplicably does not work. So the purpose of the macros
is simply to ensure that this kind of alteration will be detected by
the compiler.

And as tempted as we may be to dismiss the likelihood of such a
nightmarishly difficult bug as farfetched - or something better suited
as a plot line for a horror movie - we know that we cannot discount it.
Because as atrocious as this code may seem, the problem that it averts
is something even worse. So if we are to learn anything from examining
this code, it is that we should be much more cautious about looking
into system header files. We now know how unsettling their contents can
be. And in fact, no amount of experience can ever truly prepare a
programmer for all of the horrors found within them.

Greg


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Victor Bazarov
Guest





PostPosted: Wed May 03, 2006 10:06 am    Post subject: Re: Why redefining enumerators as macros? Reply with quote



Maxim Yegorushkin wrote:
Quote:
I could not to make up or google an explanation for this (idiom?)
often seen in system headers:

/* Standard well-defined IP protocols. */
enum
{
IPPROTO_IP = 0, /* Dummy protocol for TCP. */
#define IPPROTO_IP IPPROTO_IP
IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS
IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
#define IPPROTO_ICMP IPPROTO_ICMP
IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
#define IPPROTO_IGMP IPPROTO_IGMP
...

Could anybody shed some light on why they make enumerators
preprocessor macros? To enable for some fancy preprocessing?

I can't think of any other reason. It doesn't have to be fancy, though.
All one might want is to see if those things have been defined. Macros
are the only way a preprocessor can know if some part of the code has
already been [pre]processed.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
James Hopkin
Guest





PostPosted: Wed May 03, 2006 8:06 pm    Post subject: Re: Why redefining enumerators as macros? Reply with quote

Victor Bazarov wrote:
Quote:
Maxim Yegorushkin wrote:
I could not to make up or google an explanation for this (idiom?)
often seen in system headers:

/* Standard well-defined IP protocols. */
enum
{
IPPROTO_IP = 0, /* Dummy protocol for TCP. */
#define IPPROTO_IP IPPROTO_IP
IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS
IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
#define IPPROTO_ICMP IPPROTO_ICMP
IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
#define IPPROTO_IGMP IPPROTO_IGMP
...

Could anybody shed some light on why they make enumerators
preprocessor macros? To enable for some fancy preprocessing?

I can't think of any other reason. It doesn't have to be fancy, though.
All one might want is to see if those things have been defined. Macros
are the only way a preprocessor can know if some part of the code has
already been [pre]processed.


Good point. I wonder if the code originally said

#define IPPROTO_IP 0 /* Dummy protocol for TCP. */
#define IPPROTO_HOPOPTS 0 /* IPv6 Hop-by-Hop options. */
#define IPPROTO_ICMP 1 /* Internet Control Message Protocol. */
#define IPPROTO_IGMP 2 /* Internet Group Management Protocol. */

and when someone decided to change it to an enum, they found instances
of

#ifdef IPPROTO_IP

etc. in client code.

This must be a transitional thing, because I can't see any benefit to
it being an unnamed enum, while the macros still exist.


James


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
kanze
Guest





PostPosted: Wed May 03, 2006 9:06 pm    Post subject: Re: Why redefining enumerators as macros? Reply with quote

Maxim Yegorushkin wrote:

Quote:
I could not to make up or google an explanation for this
(idiom?) often seen in system headers:

/* Standard well-defined IP protocols. */
enum
{
IPPROTO_IP = 0, /* Dummy protocol for TCP. */
#define IPPROTO_IP IPPROTO_IP
IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS
IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
#define IPPROTO_ICMP IPPROTO_ICMP
IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
#define IPPROTO_IGMP IPPROTO_IGMP
...

Could anybody shed some light on why they make enumerators
preprocessor macros? To enable for some fancy preprocessing?

That's the only thing I can think of. If they are macros, you
can use them in pre-processor conditionals, along the lines of:

#if TARGET_IPPROTO == IPPROTO_ICMP

You can also stringize them and concatenate them as tokens.

Without seeing more, it's hard to tell, but it looks like very
little gain to me.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Alberto Ganesh Barbati
Guest





PostPosted: Wed May 03, 2006 9:06 pm    Post subject: Re: Why redefining enumerators as macros? Reply with quote

Maxim Yegorushkin ha scritto:
Quote:
Hi,

I could not to make up or google an explanation for this (idiom?) often
seen in system headers:

/* Standard well-defined IP protocols. */
enum
{
IPPROTO_IP = 0, /* Dummy protocol for TCP. */
#define IPPROTO_IP IPPROTO_IP
IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS
IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
#define IPPROTO_ICMP IPPROTO_ICMP
IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
#define IPPROTO_IGMP IPPROTO_IGMP
...

Could anybody shed some light on why they make enumerators preprocessor
macros? To enable for some fancy preprocessing?


The only reason I can think of is to allow conditional compilation as in:

#ifdef IPPROTO_IP
// do something with IP
#endif
#ifdef IPPROTO_ICMP
// do something with ICMP
#endif
// etc.

HTH,

Ganesh

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Maxim Yegorushkin
Guest





PostPosted: Thu May 04, 2006 10:21 am    Post subject: Re: Why redefining enumerators as macros? Reply with quote

kanze wrote:

[]

Quote:
Could anybody shed some light on why they make enumerators
preprocessor macros? To enable for some fancy preprocessing?

That's the only thing I can think of. If they are macros, you
can use them in pre-processor conditionals, along the lines of:

#if TARGET_IPPROTO == IPPROTO_ICMP

You can also stringize them and concatenate them as tokens.

It turned out you can stringize enumerators as well without having to
define them as macros.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
James Dennett
Guest





PostPosted: Thu May 04, 2006 10:21 am    Post subject: Re: Why redefining enumerators as macros? Reply with quote

kanze wrote:
Quote:
Maxim Yegorushkin wrote:

I could not to make up or google an explanation for this
(idiom?) often seen in system headers:

/* Standard well-defined IP protocols. */
enum
{
IPPROTO_IP = 0, /* Dummy protocol for TCP. */
#define IPPROTO_IP IPPROTO_IP
IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS
IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
#define IPPROTO_ICMP IPPROTO_ICMP
IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
#define IPPROTO_IGMP IPPROTO_IGMP
...

Could anybody shed some light on why they make enumerators
preprocessor macros? To enable for some fancy preprocessing?

That's the only thing I can think of. If they are macros, you
can use them in pre-processor conditionals, along the lines of:

#if TARGET_IPPROTO == IPPROTO_ICMP

You can also stringize them and concatenate them as tokens.

You can test them with #ifdef (or #if defined), but you
can't do anything else with them as defined above, as
macro expansion has no effect on them -- they expand to
themselves (and the preprocessor rules say that's OK).

The macro definition should at least generate a diagnostic
if some other code has defined (say) IPPROTO_IP with a
different expansion. Though I don't imagine that's the
reason it's written this way.

-- James


-- James

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
kanze
Guest





PostPosted: Fri May 05, 2006 9:21 am    Post subject: Re: Why redefining enumerators as macros? Reply with quote

James Dennett wrote:
Quote:
kanze wrote:
Maxim Yegorushkin wrote:

I could not to make up or google an explanation for this
(idiom?) often seen in system headers:

/* Standard well-defined IP protocols. */
enum
{
IPPROTO_IP = 0, /* Dummy protocol for TCP. */
#define IPPROTO_IP IPPROTO_IP
IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */
#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS
IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */
#define IPPROTO_ICMP IPPROTO_ICMP
IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */
#define IPPROTO_IGMP IPPROTO_IGMP
...

Could anybody shed some light on why they make enumerators
preprocessor macros? To enable for some fancy
preprocessing?

That's the only thing I can think of. If they are macros,
you can use them in pre-processor conditionals, along the
lines of:

#if TARGET_IPPROTO == IPPROTO_ICMP

You can also stringize them and concatenate them as tokens.

You can test them with #ifdef (or #if defined), but you can't
do anything else with them as defined above, as macro
expansion has no effect on them -- they expand to themselves
(and the preprocessor rules say that's OK).

Quite true. And as Maxim has pointed out, you can stringize the
enum symbols as well. And concatenate them. Which means that
the #ifdef is about the only possible use left.

Quote:
The macro definition should at least generate a diagnostic if
some other code has defined (say) IPPROTO_IP with a different
expansion. Though I don't imagine that's the reason it's
written this way.

That's about what I think. James Hopkin is probably right; the
code originally used the #define's. It was modified to use the
enum, and then the programmer stumbled onto someone doing an
#ifdef.

At any rate, I'd say that it is the result of an error. Either
the code guaranteed that the values were defined in the
preprocessor, in which case, defining the enum violates the
contract, or it didn't, in which case, using them in a
preprocessor expression is an error. (But we all know that
people tend to be a bit sloppy about this sort of thing -- to
find out whether a symbol is defined in the preprocessor or not,
we look at the actual header, and not the contract of the
header.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.