By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,905 Members | 1,637 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,905 IT Pros & Developers. It's quick & easy.

preprocessor and enum

P: n/a
Hi all,
We can define some magic number with #define:

#define OPERATION_1 0x00000001
#define OPERATION_2 0x00000002
#define OPERATION_3 0x00000003
....

We can also do that with enum:
enum OPERATION
{
OPERATION_1=0x00000001,
OPERATION_2=0x00000002,
OPERATION_3=0x00000003,
...
};

What make you prefer preprocessor? What make you prefer enum? Any
experience support that?

Nov 14 '05 #1
Share this Question
Share on Google+
9 Replies


P: n/a
On 2 Mar 2005 20:08:38 -0800, "ccwork" <cc****@hotmail.com> wrote:
Hi all,
We can define some magic number with #define:

#define OPERATION_1 0x00000001
#define OPERATION_2 0x00000002
#define OPERATION_3 0x00000003
...

We can also do that with enum: [...] What make you prefer preprocessor? What make you prefer enum?


Preprocessor is find with C, but should be avoided as a #define does not
have any knowledge of context and can mess things up if you don't expect
them to. (e.g. a header file defines the macro begin, which clobbers local
variable definitions.)
Nov 14 '05 #2

P: n/a

On Wed, 2 Mar 2005, ccwork wrote:

We can define some magic number with #define:

#define OPERATION_1 0x00000001
#define OPERATION_2 0x00000002
#define OPERATION_3 0x00000003
...

We can also do that with enum:
enum OPERATION
{
OPERATION_1=0x00000001,
OPERATION_2=0x00000002,
OPERATION_3=0x00000003,
...
};

What make you prefer preprocessor? What make you prefer enum? Any
experience support that?


What I say: Enums are the way to go. They give you all the benefits
of a compile-time constant, plus the benefits of the language's type
checking.
What I do: #define, #define, #define. Why? Because #defines are
easier to type. They don't require you to insert = signs everywhere,
or to count commas. (Yes, you just need to stick a comma after each
enumeration value --- but that's still a lot of extra typing, even if
it is mindless.)
There's another dumb reason I use #defines over enums: I don't have
to think about capitalization. #defined constants in C code are ALL_CAPS,
always. Enumeration constants... well, I'd have to think about that.
I'd probably lower_case enum values in most cases. But the important
thing is, I'd have to think about it. With #defines, there's a default
style that everyone knows by heart, so it's one less thing to worry
about.
Another dumb reason: Enum definitions define a new "type." Which I
usually feel deserves a name, such as

enum suit {
Hearts, Spades, Clubs, Diamonds,
};

Now, suppose I write a function that takes a suit as a parameter. Do
I write

void pick_a_card(suit s);

or do I write

void pick_a_card(int s);

? With #defines, there's no decision to make. No new type, no tricky
style decisions.

So there you have it --- I recommend 'enum' in theory, but when it
comes to actual coding (of relatively tiny stuff, I must add), I almost
always use '#define' instead, because it means fewer time-consuming
style decisions for me.

HTH, but get a second opinion,
-Arthur
Nov 14 '05 #3

P: n/a
"Arthur J. O'Dwyer" wrote:
.... snip ... Another dumb reason: Enum definitions define a new "type." Which I
usually feel deserves a name, such as

enum suit {
Hearts, Spades, Clubs, Diamonds,
};

Now, suppose I write a function that takes a suit as a parameter.
Do I write

void pick_a_card(suit s);


Which would be wrong. No suit type has been defined, only "enum
suit".

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
Nov 14 '05 #4

P: n/a
there is a small difference when it comes to compilation.
imagine you have a small number of OPERATIONS that would
fit into one byte.
your declaration would then look like this :

#define OPERATION_1 0x01
#define OPERATION_2 0x02
#define OPERATION_3 0x03

or

enum OPERATION
{
OPERATION_1=0x01,
OPERATION_2=0x02,
OPERATION_3=0x03
};

now imagine you compile the statements

unsigned char OP;
....
if(OP == OPERATION_1) { DoSomething() }

for an 8 bit processor (they are still used in embedded systems)
the comparison would take 3 assembler statements (2 byte compares
and a conditional jump) for the enum version, cause the compiler
would typecast OP to int. (typecasts always to the bigger type)
it would only take 2 assembler statements (1 compare, 1 conditional
jump) for the #define version.
Nov 14 '05 #5

P: n/a
d.********@raumcomputer.com wrote:
there is a small difference when it comes to compilation.
imagine you have a small number of OPERATIONS that would
fit into one byte.
your declaration would then look like this :

#define OPERATION_1 0x01
#define OPERATION_2 0x02
#define OPERATION_3 0x03

or

enum OPERATION
{
OPERATION_1=0x01,
OPERATION_2=0x02,
OPERATION_3=0x03
};

now imagine you compile the statements

unsigned char OP;
...
if(OP == OPERATION_1) { DoSomething() }

for an 8 bit processor (they are still used in embedded systems)
the comparison would take 3 assembler statements (2 byte compares
and a conditional jump) for the enum version, cause the compiler
would typecast OP to int. (typecasts always to the bigger type)
it would only take 2 assembler statements (1 compare, 1 conditional
jump) for the #define version.


The compiler is perfectly at liberty to implement the enum comparison
the "short way" if it so wishes. I presume C compilers for 8-bit
machines are very likely to make wishes of that kind.

--
Chris "electric hedgehog" Dollin
Nov 14 '05 #6

P: n/a
ccwork wrote:
Hi all,
We can define some magic number with #define:

#define OPERATION_1 0x00000001
#define OPERATION_2 0x00000002
#define OPERATION_3 0x00000003
...

We can also do that with enum:
enum OPERATION
{
OPERATION_1=0x00000001,
OPERATION_2=0x00000002,
OPERATION_3=0x00000003,
...
};

What make you prefer preprocessor? What make you prefer enum? Any
experience support that?


enums are the way to go I believe. They allow the compiler some more
information, which it can in turn use to help you out.

Example:

switch (foo) {
case OPERATION_1:
...
break;
case OPERATION_2:
...
break;
}

If foo is an int, that can't get you a diagnostic. If foo is an enum
the compiler (e.g. gcc with -Wall) might be able to give you something
like this:
foo.c:20: warning: enumeration value `OPERATION_2' not handled in switch

I like that. If I have a switch that doesn't have a default and doesn't
cover all the enumerated cases I think it is broken, nice that the
compiler can detect it. There may be other cases where the compiler
can do useful things given the knowledge that a value is an enumeration,
not sure though.

-David
Nov 14 '05 #7

P: n/a
d.********@raumcomputer.com wrote:
there is a small difference when it comes to compilation.
imagine you have a small number of OPERATIONS that would
fit into one byte.
your declaration would then look like this :

#define OPERATION_1 0x01
#define OPERATION_2 0x02
#define OPERATION_3 0x03

or

enum OPERATION
{
OPERATION_1=0x01,
OPERATION_2=0x02,
OPERATION_3=0x03
};

now imagine you compile the statements

unsigned char OP;
...
if(OP == OPERATION_1) { DoSomething() }

for an 8 bit processor (they are still used in embedded systems)
the comparison would take 3 assembler statements (2 byte compares
and a conditional jump) for the enum version, cause the compiler
would typecast OP to int.
If the compiler does that then the optimiser is not very good. It should
see at compile time whether OPERATION_1 is within the range of OP and if
it isn't eliminate the code and if it is do a test of the byte against
the requisite value.
(typecasts always to the bigger type)
it would only take 2 assembler statements (1 compare, 1 conditional
jump) for the #define version.


Actually, 0x01 also has a type of int, so if the compiler does not
optimise the comparison as described above you still have the problem.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 14 '05 #8

P: n/a


ccwork wrote:

Hi all,
We can define some magic number with #define:

#define OPERATION_1 0x00000001
#define OPERATION_2 0x00000002
#define OPERATION_3 0x00000003
...

We can also do that with enum:
enum OPERATION
{
OPERATION_1=0x00000001,
OPERATION_2=0x00000002,
OPERATION_3=0x00000003,
...
};

What make you prefer preprocessor? What make you prefer enum? Any
experience support that?


I like to use:
typedef enum {
XXX=0,
YYY,
ZZZ,
...
} MyEnumType_t;

This makes it easy do define a large number of UNIQUE values - using
#define to define 20 or 30 values may seem ok, but you could easily
define two to be the same value.
(Note - I only ever specify the first value for the enum).

By using a typedef, I avoid the problem mentioned by Mr. O'Dwyer:
foo( MyEnumType_t arg );

--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Common User Interface Services
M/S 2R-94 (206)544-5225
Nov 14 '05 #9

P: n/a
"ccwork" <cc****@hotmail.com> writes:
Hi all,
We can define some magic number with #define:

#define OPERATION_1 0x00000001
#define OPERATION_2 0x00000002
#define OPERATION_3 0x00000003
...

We can also do that with enum:
enum OPERATION
{
OPERATION_1=0x00000001,
OPERATION_2=0x00000002,
OPERATION_3=0x00000003,
...
};

What make you prefer preprocessor? What make you prefer enum? Any
experience support that?


I consider the use of enum this way to be a trick; it creates a
superfluous type when all that's needed is a set of constants.

However, it's a fairly common idiom, and I have no problem with using
it. I'd probably drop the tag (since you never want to use the type)
and add a comment explaining the purpose of the declaration, something
like:

/*
* This enum declaration is intended only to create a set of
* constants; the type itself is not used.
*/
enum {
OPERATION_1 = 0x00000001,
OPERATION_2 = 0x00000002,
OPERATION_3 = 0x00000003,
...
};

One drawback is that it can only create constants of type int.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #10

This discussion thread is closed

Replies have been disabled for this discussion.