Problem with ABS() macro

P

Peter Ammon

K.N. King's book "C Programming: A Modern Approach" gives this exercise
in chapter 14, which is about the preprocessor:


The following macro has a subtle problem:

#define ABS(a) ((a)<0?-(a):a)

Give an example that shows why ABS doesn't work,
and show how to fix the problem. You may assume
that the argument to ABS doesn't have a side effect.


The only potential problem I see is when INT_MIN is passed, which I do
not believe to be the solution that King has in mind. Can anyone shed
some light on this problem? Most of the other problems in the chapter
are related to not parenthesizing the arguments properly, but I can't
think of a case where the missing parenthesis could causse a problem in
the above macro.

Thanks.
-Peter
 
E

Eric Sosman

Peter said:
K.N. King's book "C Programming: A Modern Approach" gives this exercise
in chapter 14, which is about the preprocessor:


The following macro has a subtle problem:

#define ABS(a) ((a)<0?-(a):a)

Give an example that shows why ABS doesn't work,
and show how to fix the problem. You may assume
that the argument to ABS doesn't have a side effect.


The only potential problem I see is when INT_MIN is passed, which I do
not believe to be the solution that King has in mind. Can anyone shed
some light on this problem? Most of the other problems in the chapter
are related to not parenthesizing the arguments properly, but I can't
think of a case where the missing parenthesis could causse a problem in
the above macro.

Hint: Can, you, think, of, any, C, operator, without,
side, effects, but, with, lower, prececence, than, `?:'?
 
N

Novitas

The main thing is not to get hooked into considering only examples of
ABS(a) where a is a simple variable name.
 
J

Joona I Palaste

Hint: Can, you, think, of, any, C, operator, without,
side, effects, but, with, lower, prececence, than, `?:'?

So if we change the macro to:
#define ABS(a) ((a)<0 ? -(a) : (a))
and remember the assumption that the argument won't have a side effect,
then it should work?
 
P

Peter Ammon

Eric said:
Hint: Can, you, think, of, any, C, operator, without,
side, effects, but, with, lower, prececence, than, `?:'?

Yes, the comma operator. But ABS(0, -1) is treated as sending two
arguments to the ABS operator, not
 
P

Peter Ammon

Eric said:
Hint: Can, you, think, of, any, C, operator, without,
side, effects, but, with, lower, prececence, than, `?:'?

(Sorry for the double post, I hit send by mistake)

Yes, the comma operator. But ABS(0, -1) is parsed as attempting to
invoke ABS with two parameters rather than a single comma-parameter, and
ABS((0, -1)) works as expected because then the argument is already
parenthesized.

(Thinking...)

I can produce an error with the double-macro trick:

#define x 0,-1
#define ABS(a) ((a)<0?-(a):a)

Then ABS(x) is -1.

I'll have to give the book more credit if that's the solution the author
was looking for!

-Peter
 
L

Lawrence Kirby

On Wed, 29 Dec 2004 14:14:04 -0800, Peter Ammon wrote:

....
Yes, the comma operator. But ABS(0, -1) is parsed as attempting to
invoke ABS with two parameters rather than a single comma-parameter, and
ABS((0, -1)) works as expected because then the argument is already
parenthesized.

True, and for the same reason most macros don't bother to parenthesise
macro arguments that are passed on as function/macro arguments in the
macro body, e.g.

#define MYREALLOC(ptr, size) realloc(ptr, size)
(Thinking...)

I can produce an error with the double-macro trick:

#define x 0,-1
#define ABS(a) ((a)<0?-(a):a)

Then ABS(x) is -1.

Good catch, and very sneaky. A macro expanding to an unparenthesised
expression, especially a comma operator is pure evil. If anything is is
the x macro that is broken here, not the ABS() macro.
I'll have to give the book more credit if that's the solution the author
was looking for!

I'm not convinced. It is too obscure to expect somebody just learning the
language to come up with it. IMO either we're missing something or the
case that King was thinking about is wrong.

Anothing thing to consider for completeness is the conditional operator
itself, e.g. ABS(0 ? -1 : -2). However the conditional operator is right
associative so this does the right(!) thing. If it had been left
associative it would have broken King's ABS() macro.

Lawrence
 
E

Eric Sosman

Peter said:
Eric said:
Hint: Can, you, think, of, any, C, operator, without,
side, effects, but, with, lower, prececence, than, `?:'?

(Sorry for the double post, I hit send by mistake)

Yes, the comma operator. But ABS(0, -1) is parsed as attempting to
invoke ABS with two parameters [...]

Hmmm: Right you are. Good catch!
(Thinking...)

I can produce an error with the double-macro trick:

#define x 0,-1
#define ABS(a) ((a)<0?-(a):a)

Then ABS(x) is -1.

Sneaky, evil, admirable, ... and a sign of a twisted mind.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,157
Messages
2,570,879
Members
47,414
Latest member
djangoframe

Latest Threads

Top