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

Extreme Efficiency for Odd/Even

P: n/a

I'm trying to write extremely efficient, fully portable algorithms to
determine if an integer is odd or even. The most basic algorithms would be:

#define IS_ODD(x) ((x) % 2)

#define IS_EVEN(x) (!((x) % 2))

Attempting to make them slightly more efficient, we could change them to:

#define IS_ODD(x) ((x) & 1)

#define IS_EVEN(x) (!((x) & 1))

(Yes, some compilers may actually compile the former into the latter, but
we're playing the efficiency game here.)

Only thing though:-
The latter two will malfunction on One's Complement systems when
dealing with negative numbers. Thus, I have the following code... I'd
appreciate any comments or suggestions. No changes are required for Sign-
magnitude or for Two's Complement, but we must improvise for One's
Complement. Here we go:

#define SIGNMAG 0
#define ONES 1
#define TWOS 2

#if -1 & 3 == 1
#define NUMSYS SIGNMAG
#elif -1 & 3 == 2
#define NUMSYS ONES
#else
#define NUMSYS TWOS
#endif

#if NUMSYS != ONES
#define IS_ODD(x) ((x) & 1)
#define IS_EVEN(x) (!((x) & 1))
#else
#define ONE_IF_NEGATIVE(x) ((x) < 0)

#define IS_ODD(x) ( !((x) & 1) == ONE_IF_NEGATIVE((x)) )
#define IS_EVEN(x) ( !((x) & 1) != ONE_IF_NEGATIVE((x)) )
#endif

Unfortunately though, the One's Complement version evaluates the argument
twice.

Yes, I realise that the smart thing would probably just be to write "x %
2" and forget about it, but this is more for kicks than anything else.

--

Frederick Gotham
Sep 11 '06 #1
Share this Question
Share on Google+
34 Replies


P: n/a
Frederick Gotham <fg*******@SPAM.comwrites:
I'm trying to write extremely efficient, fully portable algorithms to
determine if an integer is odd or even.
[cut]
#if -1 & 3 == 1
I'm not really sure if you can assume that preprocessor uses the same
arithmetic as the program will use itself. What if you are compiling
a program for one architecture on another - like compiling for ix86
(which is two's complement) on some one's complement system.

[one's compelment version:]
#define ONE_IF_NEGATIVE(x) ((x) < 0)
#define IS_ODD(x) ( !((x) & 1) == ONE_IF_NEGATIVE((x)) )
#define IS_EVEN(x) ( !((x) & 1) != ONE_IF_NEGATIVE((x)) )
#v+
#define IS_ODD(x) ((x) % 2)
#define IS_EVEN(x) (!IS_ODD(x))
#v-

Would probably be faster anyway.
Yes, I realise that the smart thing would probably just be to write "x %
2" and forget about it, but this is more for kicks than anything else.
If you really want portability you should stick to '% 2' version and
let compiler do the optimization.

--
Best regards, _ _
.o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
..o | Computer Science, Michal "mina86" Nazarewicz (o o)
ooo +--<mina86*tlen.pl>--<jid:mina86*jabber.org>--ooO--(_)--Ooo--
Sep 11 '06 #2

P: n/a
Michal Nazarewicz wrote:
Frederick Gotham <fg*******@SPAM.comwrites:
> #define ONE_IF_NEGATIVE(x) ((x) < 0)
#define IS_ODD(x) ((x) % 2)
Would probably be faster anyway.
It's been a long time I optimized code for speed, but wouldn't

#define IS_ODD(x) ((x) & 1)

be even faster? Doesn't modulo always require a time-consuming division
(if the compiler isn't clever enough to handle modulo 2 differently)?

Regards
Steffen
Sep 11 '06 #3

P: n/a
Michal Nazarewicz wrote:
Frederick Gotham <fg*******@SPAM.comwrites:
I'm trying to write extremely efficient, fully portable algorithms to
determine if an integer is odd or even.
[cut]
#if -1 & 3 == 1

I'm not really sure if you can assume that preprocessor uses the same
arithmetic as the program will use itself. What if you are compiling
a program for one architecture on another - like compiling for ix86
(which is two's complement) on some one's complement system.
In C99, that's a safe assumption. Preprocessor arithmetic is done (as
if) in the target's (u)intmax_t types. IIRC C99 changed the rules for
that, though, so it may not be safe in C89.

Sep 11 '06 #4

P: n/a
Steffen Buehler <st*************@mailinator.comwrites:
Michal Nazarewicz wrote:
>Frederick Gotham <fg*******@SPAM.comwrites:
>> #define ONE_IF_NEGATIVE(x) ((x) < 0)
>#define IS_ODD(x) ((x) % 2)
>Would probably be faster anyway.

It's been a long time I optimized code for speed, but wouldn't

#define IS_ODD(x) ((x) & 1)

be even faster? Doesn't modulo always require a time-consuming division
(if the compiler isn't clever enough to handle modulo 2 differently)?
It would but won't work in one's complement arithmetic and I was
referring to IS_ODD, IS_EVEN macros defined for such arithmetic.

(The other thing is that compiler is free to optimize the code in such
a way that AND instruction will be used in both cases if appropriate)

--
Best regards, _ _
.o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
..o | Computer Science, Michal "mina86" Nazarewicz (o o)
ooo +--<mina86*tlen.pl>--<jid:mina86*jabber.org>--ooO--(_)--Ooo--
Sep 11 '06 #5

P: n/a
=?utf-8?B?SGFyYWxkIHZhbiBExLNr?= posted:
>I'm not really sure if you can assume that preprocessor uses the same
arithmetic as the program will use itself. What if you are compiling
a program for one architecture on another - like compiling for ix86
(which is two's complement) on some one's complement system.

In C99, that's a safe assumption. Preprocessor arithmetic is done (as
if) in the target's (u)intmax_t types. IIRC C99 changed the rules for
that, though, so it may not be safe in C89.

In this any site on the internet which explains how preprocessor arithmetic
works and so forth?

--

Frederick Gotham
Sep 11 '06 #6

P: n/a
Frederick Gotham wrote:
=?utf-8?B?SGFyYWxkIHZhbiBExLNr?= posted:
I'm not really sure if you can assume that preprocessor uses the same
arithmetic as the program will use itself. What if you are compiling
a program for one architecture on another - like compiling for ix86
(which is two's complement) on some one's complement system.
In C99, that's a safe assumption. Preprocessor arithmetic is done (as
if) in the target's (u)intmax_t types. IIRC C99 changed the rules for
that, though, so it may not be safe in C89.

In this any site on the internet which explains how preprocessor arithmetic
works and so forth?
I'm not aware of one, but for C99 it's quite simple. There are
effectively only two types during preprocessor arithmetic: a signed
one, and an unsigned one. Everything has the same width and
representation, and they must match those of the target's intmax_t and
uintmax_t types.

Sep 11 '06 #7

P: n/a
In article <e0*******************@news.indigo.ie>,
Frederick Gotham <fg*******@SPAM.comwrote:
>=?utf-8?B?SGFyYWxkIHZhbiBExLNr?= posted:
>>I'm not really sure if you can assume that preprocessor uses the same
arithmetic as the program will use itself. What if you are compiling
a program for one architecture on another - like compiling for ix86
(which is two's complement) on some one's complement system.

In C99, that's a safe assumption. Preprocessor arithmetic is done (as
if) in the target's (u)intmax_t types. IIRC C99 changed the rules for
that, though, so it may not be safe in C89.


In this any site on the internet which explains how preprocessor arithmetic
works and so forth?
No, it isn't. It is a Usenet newsgroup.

Sep 11 '06 #8

P: n/a

Frederick Gotham wrote:
I'm trying to write extremely efficient, fully portable algorithms to
determine if an integer is odd or even. The most basic algorithms would be:

#define IS_ODD(x) ((x) % 2)

#define IS_EVEN(x) (!((x) % 2))

Attempting to make them slightly more efficient, we could change them to:

#define IS_ODD(x) ((x) & 1)

#define IS_EVEN(x) (!((x) & 1))

(Yes, some compilers may actually compile the former into the latter, but
we're playing the efficiency game here.)

Only thing though:-
The latter two will malfunction on One's Complement systems when
dealing with negative numbers. Thus, I have the following code... I'd
appreciate any comments or suggestions. No changes are required for Sign-
magnitude or for Two's Complement, but we must improvise for One's
Complement. Here we go:

#define SIGNMAG 0
#define ONES 1
#define TWOS 2

#if -1 & 3 == 1
#define NUMSYS SIGNMAG
#elif -1 & 3 == 2
#define NUMSYS ONES
#else
#define NUMSYS TWOS
#endif

#if NUMSYS != ONES
#define IS_ODD(x) ((x) & 1)
#define IS_EVEN(x) (!((x) & 1))
#else
#define ONE_IF_NEGATIVE(x) ((x) < 0)

#define IS_ODD(x) ( !((x) & 1) == ONE_IF_NEGATIVE((x)) )
#define IS_EVEN(x) ( !((x) & 1) != ONE_IF_NEGATIVE((x)) )
#endif
Whats wrong with

#define IS_ODD(x) ((unsigned)(x) & 1)

Mark Williams

Sep 11 '06 #9

P: n/a
mark posted:
Whats wrong with

#define IS_ODD(x) ((unsigned)(x) & 1)

Let's test it.

If we try it with an expression of type "int" whose value is -5, then we
get:

(unsigned)-5 & 1

which is equivalent to:

(unsigned)UINT_MAX - (5-1) & 1

which, for 16-Bit int's would be:

65535U - (5-1) & 1

65531 & 1

which would register as an odd number.

Looks good. Only thing though, I wonder if the machine would have to do any
processing in order to convert the -5 to an unsigned integer expression?

--

Frederick Gotham
Sep 11 '06 #10

P: n/a
Frederick Gotham posted:
65531 & 1
I should have written:

65531U & 1

--

Frederick Gotham
Sep 11 '06 #11

P: n/a
Frederick Gotham wrote:
I'm trying to write extremely efficient, fully portable algorithms to
determine if an integer is odd or even. The most basic algorithms would be:

#define IS_ODD(x) ((x) % 2)

#define IS_EVEN(x) (!((x) % 2))

Attempting to make them slightly more efficient, we could change them to:

#define IS_ODD(x) ((x) & 1)

#define IS_EVEN(x) (!((x) & 1))

(Yes, some compilers may actually compile the former into the latter, but
we're playing the efficiency game here.)
If x is an unknown signed int, then many/most compilers _can't_ compile
the former to the latter. [Or at least not without additional checks.]

Note that x&1 produces 0 or 1, but x % 2 can produce -1, 0 or 1.

--
Peter

Sep 11 '06 #12

P: n/a
Peter Nilsson wrote:
Frederick Gotham wrote:
>I'm trying to write extremely efficient, fully portable algorithms to
determine if an integer is odd or even. The most basic algorithms would be:

#define IS_ODD(x) ((x) % 2)

#define IS_EVEN(x) (!((x) % 2))

Attempting to make them slightly more efficient, we could change them to:

#define IS_ODD(x) ((x) & 1)

#define IS_EVEN(x) (!((x) & 1))

(Yes, some compilers may actually compile the former into the latter, but
we're playing the efficiency game here.)

If x is an unknown signed int, then many/most compilers _can't_ compile
the former to the latter. [Or at least not without additional checks.]

Note that x&1 produces 0 or 1, but x % 2 can produce -1, 0 or 1.
Which is mostly irrelevant, since IS_ODD(x) will typically be used as a
conditional expression. ((x) % 2) is equivalent to ((x) % 2) != 0 in those
circumstances, which always works.

I think you'll find compilers can optimize this quite nicely, and many will,
since parity testing is quite common and generic modulo is typically slow.

S.
Sep 11 '06 #13

P: n/a
Skarmander wrote:
Peter Nilsson wrote:
Frederick Gotham wrote:
I'm trying to write extremely efficient, fully portable algorithms to
determine if an integer is odd or even. The most basic algorithms would be:

#define IS_ODD(x) ((x) % 2)

#define IS_EVEN(x) (!((x) % 2))

Attempting to make them slightly more efficient, we could change them to:

#define IS_ODD(x) ((x) & 1)

#define IS_EVEN(x) (!((x) & 1))

(Yes, some compilers may actually compile the former into the latter, but
we're playing the efficiency game here.)
If x is an unknown signed int, then many/most compilers _can't_ compile
the former to the latter. [Or at least not without additional checks.]

Note that x&1 produces 0 or 1, but x % 2 can produce -1, 0 or 1.

Which is mostly irrelevant, since IS_ODD(x) will typically be used as a
conditional expression. ((x) % 2) is equivalent to ((x) % 2) != 0 in those
circumstances, which always works.
You're ignoring the disease because you _think_ the symptoms are
trivial.
In C, the symptoms of bugs may be subtle, but they are rarely trivial.
I think you'll find compilers can optimize this quite nicely, and many will,
since parity testing is quite common and generic modulo is typically slow.
Which just reinforces the reasons behind just using % in the first
place...

#define IS_ODD(x) ((x) % 2 != 0)
#define IS_EVEN(x) ((x) % 2 == 0)

--
Peter

Sep 11 '06 #14

P: n/a
Peter Nilsson wrote:
Skarmander wrote:
>Peter Nilsson wrote:
>>Frederick Gotham wrote:
I'm trying to write extremely efficient, fully portable algorithms to
determine if an integer is odd or even. The most basic algorithms would be:

#define IS_ODD(x) ((x) % 2)

#define IS_EVEN(x) (!((x) % 2))

Attempting to make them slightly more efficient, we could change them to:

#define IS_ODD(x) ((x) & 1)

#define IS_EVEN(x) (!((x) & 1))

(Yes, some compilers may actually compile the former into the latter, but
we're playing the efficiency game here.)
If x is an unknown signed int, then many/most compilers _can't_ compile
the former to the latter. [Or at least not without additional checks.]

Note that x&1 produces 0 or 1, but x % 2 can produce -1, 0 or 1.
Which is mostly irrelevant, since IS_ODD(x) will typically be used as a
conditional expression. ((x) % 2) is equivalent to ((x) % 2) != 0 in those
circumstances, which always works.

You're ignoring the disease because you _think_ the symptoms are
trivial.
In C, the symptoms of bugs may be subtle, but they are rarely trivial.
Oh, come on. You know the fix already, which is to add the test to *force*
this expression to always be a conditional expression. Do you really think
I'm advocating leaving it as-is? I for one hate crypto-conditional
expressions (doing it for pointers is one thing, but non-boolean integral
expressions are right out), so I would have added the test even if I had
*not* been aware of the subtlety, and I would have avoided a potential
source of bugs in the process.

There's no "disease" here, just an expression that might not do what you
think it does. If that's a disease, then C is positively plague-ridden. My
comment was intended to specifically criticize your rather spurious "the
compiler can't compile this like that" angle. In those cases where the
expression evaluates to what you expect it evaluates, the compiler can
certainly do this and probably will. In those cases where the expression
doesn't evaluate to what you think it evaluates, what the compiler does to
it doesn't matter.

We are in agreement; I just think you pointed out the issue in a misleading way.

S.
Sep 12 '06 #15

P: n/a
Frederick Gotham wrote:
mark posted:
>Whats wrong with

#define IS_ODD(x) ((unsigned)(x) & 1)


Let's test it.
Better yet, let's think about it.
If we try it with an expression of type "int" whose value is -5, then we
get:
<snip>
The type of the expression is irrelevant (well, as long as it's integral, of
course). "If the new type is unsigned, the value is converted by repeatedly
adding or subtracting one more than the maximum value that can be
represented in the new type until the value is in the range of the new type."

In fact, not even the unsigned type is relevant; all that matters is that
its maximum value is odd, so that adding or subtracting one plus the maximum
value preserves parity. As luck would have it (well, not really), the
maximum values of unsigned types are always odd, since they're one less than
a power of two.
Looks good. Only thing though, I wonder if the machine would have to do any
processing in order to convert the -5 to an unsigned integer expression?
You don't know and probably shouldn't care. Aside from that, you're on the
wrong level. This expression passes the compiler first, and there's no
guarantee what it will actually to obtain the result. A smart compiler won't
generate instructions for explicit conversion if that's not the best
approach, but then again, a smart compiler would also handle "x % 2 != 0"
efficiently, so you're down to guessing.

That said, if you really have an aversion to "x % 2 != 0" on guessological
grounds, this alternative is about as good as it gets. It's certainly better
than the code you posted upthread for one's complement machines, which can
fail on -0 (and is less likely to be optimized well). The moral of that
story is to not construct clever solutions for simple problems; you just end
up with more problems.

S.
Sep 12 '06 #16

P: n/a
Peter Nilsson wrote:
#define IS_ODD(x) ((x) % 2 != 0)
#define IS_EVEN(x) (!IS_ODD(x))

--
pete
Sep 12 '06 #17

P: n/a
Skarmander wrote:
>
Frederick Gotham wrote:
mark posted:
Whats wrong with

#define IS_ODD(x) ((unsigned)(x) & 1)

Let's test it.
Better yet, let's think about it.
If we try it with an expression of type "int"
whose value is -5, then we
get:
<snip>
The type of the expression is irrelevant
(well, as long as it's integral, of course).
"If the new type is unsigned, the value is converted by repeatedly
adding or subtracting one more than the maximum value that can be
represented in the new type until the value is
in the range of the new type."

In fact, not even the unsigned type is relevant;
all that matters is that its maximum value is odd,
so that adding or subtracting one plus the maximum
value preserves parity. As luck would have it
(well, not really), the maximum values of unsigned types
are always odd, since they're one less than a power of two.
Looks good. Only thing though,
I wonder if the machine would have to do any
processing in order to convert the -5
to an unsigned integer expression?
If INT_MIN equals (-INT_MAX - 1)
and UINT_MAX equals (2 * INT_MAX + 1)
then, -5 and (unsigned)-5,
have identical representations.

--
pete
Sep 12 '06 #18

P: n/a
pete wrote:
>
Skarmander wrote:

Frederick Gotham wrote:
mark posted:
>
>Whats wrong with
>>
>#define IS_ODD(x) ((unsigned)(x) & 1)
>
>
Let's test it.
>
Better yet, let's think about it.
If we try it with an expression of type "int"
whose value is -5, then we
get:
>
<snip>
Looks good. Only thing though,
I wonder if the machine would have to do any
processing in order to convert the -5
to an unsigned integer expression?

If INT_MIN equals (-INT_MAX - 1)
and UINT_MAX equals (2 * INT_MAX + 1)
and UINT_MAX equals (2U * INT_MAX + 1)
then, -5 and (unsigned)-5,
have identical representations.
--
pete
Sep 12 '06 #19

P: n/a

Frederick Gotham wrote:
I'm trying to write extremely efficient, fully portable algorithms to
determine if an integer is odd or even. The most basic algorithms would be:

#define IS_ODD(x) ((x) % 2)

#define IS_EVEN(x) (!((x) % 2))

Attempting to make them slightly more efficient, we could change them to:

#define IS_ODD(x) ((x) & 1)

#define IS_EVEN(x) (!((x) & 1))
1. Function macros are evil.
2. You are assuming two's complement.
http://groups.google.com/group/comp....979c1d11727a8d

Sep 12 '06 #20

P: n/a
posted:
>
Frederick Gotham wrote:
>I'm trying to write extremely efficient, fully portable algorithms to
determine if an integer is odd or even. The most basic algorithms would
be:

#define IS_ODD(x) ((x) % 2)

#define IS_EVEN(x) (!((x) % 2))

Attempting to make them slightly more efficient, we could change them
to:

#define IS_ODD(x) ((x) & 1)

#define IS_EVEN(x) (!((x) & 1))

1. Function macros are evil.

That's C++ speak.

2. You are assuming two's complement.

You're replying before reading the entire post.

--

Frederick Gotham
Sep 12 '06 #21

P: n/a
Skarmander posted:
>I wonder if the machine would have to do any processing in order to
convert the -5 to an unsigned integer expression?
You don't know and probably shouldn't care. Aside from that, you're on
the wrong level.

We have already achieved our objective -- we have a fool-proof method of
determing whether an integer is odd or even.

The objective here is different. The objective here is to perform the task
efficiently. If processing need be done to convert -5 to an unsigned
integer expression, then I _do_ care.

It's certainly better than the code you posted upthread for one's
complement machines, which can fail on -0 (and is less likely to be
optimized well). The moral of that story is to not construct clever
solutions for simple problems; you just end up with more problems.

Here's a verbatim quote from my original post:

| Yes, I realise that the smart thing would probably just
| be to write "x % 2" and forget about it, but this is
| more for kicks than anything else.

--

Frederick Gotham
Sep 12 '06 #22

P: n/a
Frederick Gotham wrote:
Skarmander posted:
>>I wonder if the machine would have to do any processing in order to
convert the -5 to an unsigned integer expression?
You don't know and probably shouldn't care. Aside from that, you're on
the wrong level.


We have already achieved our objective -- we have a fool-proof method of
determing whether an integer is odd or even.
Multiple, in fact.
The objective here is different. The objective here is to perform the task
efficiently. If processing need be done to convert -5 to an unsigned
integer expression, then I _do_ care.
So your question is: "could people with experience on one's complement
machines tell me how the compilers they've used compile the expression
'(unsigned) x & 1', and in particular whether it involves generating
instructions for converting x to unsigned, and in particular how efficient
those instructions are"?

Fair enough.
>It's certainly better than the code you posted upthread for one's
complement machines, which can fail on -0 (and is less likely to be
optimized well). The moral of that story is to not construct clever
solutions for simple problems; you just end up with more problems.


Here's a verbatim quote from my original post:

| Yes, I realise that the smart thing would probably just
| be to write "x % 2" and forget about it, but this is
| more for kicks than anything else.
I get my kicks from spoiling your fun. I hate fun, you see. If programmers
had less fun hacking, I would have more fun maintaining programs.

So, don't mind if I *do* tell you every two paragraphs that you should be
spending your time on something else, even if this is terribly presuming.
Since you already know that the obvious solution is probably the most
appropriate one, you can just ignore me. (Except where I said that your
original elaborate solution is wrong, since that's actually true.)

S.
Sep 12 '06 #23

P: n/a
Frederick Gotham wrote:
posted:
>Frederick Gotham wrote:
>>I'm trying to write extremely efficient, fully portable algorithms to
determine if an integer is odd or even. The most basic algorithms would
be:

#define IS_ODD(x) ((x) % 2)

#define IS_EVEN(x) (!((x) % 2))

Attempting to make them slightly more efficient, we could change them
to:

#define IS_ODD(x) ((x) & 1)

#define IS_EVEN(x) (!((x) & 1))
1. Function macros are evil.


That's C++ speak.
Actually no. Now that C has inline functions many of the arguments that
C++-ers have used against function macros for years now apply to C. I
would write those as inline functions and only switch to macros after
profiling shows that they are indeed slower.

This would take care of your double-evaluation problem in your
ones-compliment version.

#include <stdbool.h>

#define SIGNMAG 0
#define ONES 1
#define TWOS 2

#if -1 & 3 == 1
#define NUMSYS SIGNMAG
#elif -1 & 3 == 2
#define NUMSYS ONES
#else
#define NUMSYS TWOS
#endif

#if NUMSYS != ONES
/* Or maybe use uintmax_t instead of unsigned */
inline bool IsOdd(unsigned x) { return x & 1; }
inline bool IsEven(unsigned x) { return !(x & 1); }
#else
inline bool IsOdd(unsigned x) { return (x >= 0) == (x & 1); }
inline bool IsEven(unsigned x) { return (x >= 0) != (x & 1); }
#endif
--
Clark S. Cox III
cl*******@gmail.com
Sep 12 '06 #24

P: n/a
"Clark S. Cox III" <cl*******@gmail.comwrites:
Frederick Gotham wrote:
> posted:
>>1. Function macros are evil.

That's C++ speak.

Actually no. Now that C has inline functions many of the arguments that
C++-ers have used against function macros for years now apply to C. I
would write those as inline functions and only switch to macros after
profiling shows that they are indeed slower.
Oh pleas... Even *if* macros are evil it doesn't mean *never* use
them. They are good for small subroutines such as IS_ODD/IS_EVEN.

--
Best regards, _ _
.o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
..o | Computer Science, Michal "mina86" Nazarewicz (o o)
ooo +--<mina86*tlen.pl>--<jid:mina86*jabber.org>--ooO--(_)--Ooo--
Sep 12 '06 #25

P: n/a
Michal Nazarewicz wrote:
"Clark S. Cox III" <cl*******@gmail.comwrites:
>Frederick Gotham wrote:
>> posted:
1. Function macros are evil.
That's C++ speak.
Actually no. Now that C has inline functions many of the arguments that
C++-ers have used against function macros for years now apply to C. I
would write those as inline functions and only switch to macros after
profiling shows that they are indeed slower.

Oh pleas... Even *if* macros are evil it doesn't mean *never* use
them. They are good for small subroutines such as IS_ODD/IS_EVEN.
Did I say to never use them? No. I did not. Please do not put words into
my mouth.
--
Clark S. Cox III
cl*******@gmail.com
Sep 12 '06 #26

P: n/a
"Clark S. Cox III" <cl*******@gmail.comwrites:
Michal Nazarewicz wrote:
>Oh pleas... Even *if* macros are evil it doesn't mean *never* use
them. They are good for small subroutines such as IS_ODD/IS_EVEN.

Did I say to never use them? No. I did not. Please do not put words into
my mouth.
Not directly but saying IS_ODD/IS_EVEN should be made into inline
function sounds like "do note ever use macros 'cuz they're evil."
--
Best regards, _ _
.o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
..o | Computer Science, Michal "mina86" Nazarewicz (o o)
ooo +--<mina86*tlen.pl>--<jid:mina86*jabber.org>--ooO--(_)--Ooo--
Sep 12 '06 #27

P: n/a
Michal Nazarewicz wrote:
"Clark S. Cox III" <cl*******@gmail.comwrites:
>Michal Nazarewicz wrote:
>>Oh pleas... Even *if* macros are evil it doesn't mean *never* use
them. They are good for small subroutines such as IS_ODD/IS_EVEN.
Did I say to never use them? No. I did not. Please do not put words into
my mouth.

Not directly but saying IS_ODD/IS_EVEN should be made into inline
function sounds like "do note ever use macros 'cuz they're evil."
Whatever it sounds like to you, that is not what I said. Here is what I
said:

"Now that C has inline functions many of the arguments that
C++-ers have used against function macros for years now apply to C. I
would write those as inline functions and only switch to macros after
profiling shows that they are indeed slower."

Pay close attention to "I would..."; it has a very different meaning
than "You should always...". Also, pay close attention to "switch to
macros after profiling shows that they are indeed slower."

--
Clark S. Cox III
cl*******@gmail.com
Sep 12 '06 #28

P: n/a
"Clark S. Cox III" <cl*******@gmail.comwrites:
[...]
Actually no. Now that C has inline functions many of the arguments that
C++-ers have used against function macros for years now apply to C. I
would write those as inline functions and only switch to macros after
profiling shows that they are indeed slower.
Many, but not all. For one thing, few C compilers fully support the
C99 standard; C90 doesn't have inline functions.

--
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.
Sep 12 '06 #29

P: n/a
Keith Thompson wrote:
"Clark S. Cox III" <cl*******@gmail.comwrites:
[...]
>Actually no. Now that C has inline functions many of the arguments that
C++-ers have used against function macros for years now apply to C. I
would write those as inline functions and only switch to macros after
profiling shows that they are indeed slower.

Many, but not all. For one thing, few C compilers fully support the
C99 standard; C90 doesn't have inline functions.
True, but of the parts of C99 that *are* implemented, I'd imagine that
"inline" is one of the most common.

Of course, YMMV.

--
Clark S. Cox III
cl*******@gmail.com
Sep 13 '06 #30

P: n/a

Michal Nazarewicz wrote:
"Clark S. Cox III" <cl*******@gmail.comwrites:
Michal Nazarewicz wrote:
Oh pleas... Even *if* macros are evil it doesn't mean *never* use
them. They are good for small subroutines such as IS_ODD/IS_EVEN.
Did I say to never use them? No. I did not. Please do not put words into
my mouth.

Not directly but saying IS_ODD/IS_EVEN should be made into inline
function sounds like "do note ever use macros 'cuz they're evil."
Using macros as functions is a very bad idea. There is no type
checking performed at all. Sometimes you will get an error message as
a side effect (e.g. in the IS_ODD() macro a double or pointer would
object to the & operator ... but you might also have a macro that
increments which would work willy-nilly on pointers, doubles, ints,
etc.). Macros can be redefined to something else.

They have all sorts of evil side effects. Using macros as functions is
the product of a lazy mind -- {ironically} hard at work doing as little
thinking as possible.

See (for instance):
http://www.thescripts.com/forum/thread62551.html

That having been said, I do it myself -- once in a while.

Macros are useful -- for instance -- for conditional compiling or
creating idempotent headers. But function macros are bug engines of
the worst kind.
--
Best regards, _ _
.o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
..o | Computer Science, Michal "mina86" Nazarewicz (o o)
ooo +--<mina86*tlen.pl>--<jid:mina86*jabber.org>--ooO--(_)--Ooo--
Sep 13 '06 #31

P: n/a
"Clark S. Cox III" <cl*******@gmail.comwrites:
"Now that C has inline functions many of the arguments that
C++-ers have used against function macros for years now apply to C. I
would write those as inline functions and only switch to macros after
profiling shows that they are indeed slower."
Do you really think a sequence which involves two instructions (namely
'%'/'&' and '=='/'!=') is worth that effort? The fact that macros are
evil doesn't mean one should do ridiculous things.

--
Best regards, _ _
.o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
..o | Computer Science, Michal "mina86" Nazarewicz (o o)
ooo +--<mina86*tlen.pl>--<jid:mina86*jabber.org>--ooO--(_)--Ooo--
Sep 13 '06 #32

P: n/a
dc*****@connx.com writes:
Using macros as functions is a very bad idea. There is no type
checking performed at all. Sometimes you will get an error message as
a side effect (e.g. in the IS_ODD() macro a double or pointer would
object to the & operator ... but you might also have a macro that
increments which would work willy-nilly on pointers, doubles, ints,
etc.). Macros can be redefined to something else.
I'm not saying macros ain't evil but C gives you a lot of
opportunities to shoot yourself in your leg and still macros make live
easier in some situations and if someone really wants IS_ODD/IS_EVEN
then defining those as macros is probably one of such situations.

--
Best regards, _ _
.o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
..o | Computer Science, Michal "mina86" Nazarewicz (o o)
ooo +--<mina86*tlen.pl>--<jid:mina86*jabber.org>--ooO--(_)--Ooo--
Sep 13 '06 #33

P: n/a
Michal Nazarewicz wrote:
"Clark S. Cox III" <cl*******@gmail.comwrites:
> "Now that C has inline functions many of the arguments that
C++-ers have used against function macros for years now apply to C. I
would write those as inline functions and only switch to macros after
profiling shows that they are indeed slower."

Do you really think a sequence which involves two instructions (namely
'%'/'&' and '=='/'!=') is worth that effort?
It's not significantly more effort to write an inline function than
it is to write the corresponding function macro.

(It's even less effort to write a non-inline function for the same
thing.)

--
Chris "falling further in" Dollin
The "good old days" used to be much better.

Sep 13 '06 #34

P: n/a

Chris Dollin wrote:
Michal Nazarewicz wrote:
"Clark S. Cox III" <cl*******@gmail.comwrites:
"Now that C has inline functions many of the arguments that
C++-ers have used against function macros for years now apply to C. I
would write those as inline functions and only switch to macros after
profiling shows that they are indeed slower."
Do you really think a sequence which involves two instructions (namely
'%'/'&' and '=='/'!=') is worth that effort?

It's not significantly more effort to write an inline function than
it is to write the corresponding function macro.
And that function will have type checking and also be immune to evil
macro side effects.
Using macros for functions is both lazy and stupid. Of course, I have
admitted that I do it from time to time {what does that say about
me...}
(It's even less effort to write a non-inline function for the same
thing.)
Which most compilers will inline if you ask them to (and in a way that
is smarter than you, for the most part).
--
Chris "falling further in" Dollin
The "good old days" used to be much better.
/* Some people might even be surprised by the output of this: */
#define square(x) ((x)*(x))
#define even(x) ((((x)>>1)<<1) == (x))

#include <stdio.h>
int main(void)
{
long long ll = 217;
long l = 19;
int i = 2;
char c = 8;

if (even(square(++c)))
puts("square of 8+1 is even");
else
puts("square of 8+1 is odd");

if (even(square(++i)))
puts("square of 2+1 is even");
else
puts("square of 2+1 is odd");

if (even(square(++l)))
puts("square of 19+1 is even");
else
puts("square of 19+1 is odd");

if (even(square(++ll)))
puts("square of 217+1 is even");
else
puts("square of 217+1 is odd");

ll = 217;
l = 19;
i = 2;
c = 8;

printf("218 squared = %.0f\n", (double) square(++ll));
printf("20 squared = %.0f\n", (double) square(++l));
printf("3 squared = %.0f\n", (double) square(++i));
printf("9 squared = %.0f\n", (double) square(++c));

ll = 217;
l = 19;
i = 2;
c = 8;

if (even(++ll))
puts("218 is even");
else
puts("218 is odd");

if (even(++ll))
puts("20 is even");
else
puts("20 is odd");

if (even(++ll))
puts("3 is even");
else
puts("3 is odd");

if (even(++ll))
puts("9 is even");
else
puts("9 is odd");

return 0;
}
/*
dcorbit@DCORBIT64 /c/tmp
$ gcc -Wall -ansi -pedantic t.c
t.c: In function 'main':
t.c:7: warning: ISO C90 does not support 'long long'
t.c:37: warning: operation on 'll' may be undefined
t.c:38: warning: operation on 'l' may be undefined
t.c:39: warning: operation on 'i' may be undefined
t.c:40: warning: operation on 'c' may be undefined

dcorbit@DCORBIT64 /c/tmp
$ ./a
square of 8+1 is odd
square of 2+1 is odd
square of 19+1 is odd
square of 217+1 is odd
218 squared = 47961
20 squared = 441
3 squared = 16
9 squared = 90
218 is odd
20 is odd
3 is odd
9 is odd

dcorbit@DCORBIT64 /c/tmp
$
*/

Of course, nasal demons are another possible output.

Sep 15 '06 #35

This discussion thread is closed

Replies have been disabled for this discussion.