How can MIN macro without :? be written?

L

lovecreatesbea...

#define MIN(x, y) ((x)<(y) ? (x):(y))

Can a version without conditional operator of MIN macro be written?
 
G

Guest

Ben said:
Here's an expression, without the obfuscation of a macro:
x * (x < y) + y * !(x < y)

You're assuming that 1 * x == x, and that 0 * x == 0. This is not
necessarily true. For example, in floating point arithmetic, using your
expression with an infinity will result in NaN. For another example, if
x is a pointer, 1 * x and 0 * x are not valid expressions.
 
S

Simon Biber

#define MIN(x, y) ((x)<(y) ? (x):(y))

Can a version without conditional operator of MIN macro be written?

Yes, it can. I won't give you a solution, but point you in a direction.

Think about what the value of (x)<(y) is. How could you manipulate that
value, to give a value that is x if x is the minimum? How then could you
get y if y is the minimum? How can you combine them together? What
happens if they are the same value?
 
B

Ben Pfaff

Harald van Dijk said:
You're assuming that 1 * x == x, and that 0 * x == 0. This is not
necessarily true. For example, in floating point arithmetic, using your
expression with an infinity will result in NaN. For another example, if
x is a pointer, 1 * x and 0 * x are not valid expressions.

I was assuming that x and y are integers. Generally that's what
programmers pass to a MIN macro.

This is another reason to avoid macros: people have more
surprising ways to use them than they do with functions.
 
K

Kenneth Brody

#define MIN(x, y) ((x)<(y) ? (x):(y))

Can a version without conditional operator of MIN macro be written?

Is this cheating?

#define MIN(x,y) ( (x)+(y) - MAX(x,y) )

:)

(Yes, I'm ignoring things like integer overflow, loss of floating point
precision, pointers, and so on.)

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
K

Keith Thompson

Kenneth Brody said:
Is this cheating?

#define MIN(x,y) ( (x)+(y) - MAX(x,y) )

:)

(Yes, I'm ignoring things like integer overflow, loss of floating point
precision, pointers, and so on.)

Yes, it's cheating, because you're ignoring things like integer
overflow, loss of floating point precision, pointers, and so on.
 
S

Serve Laurijssen

Keith Thompson said:
Yes, it's cheating, because you're ignoring things like integer
overflow, loss of floating point precision, pointers, and so on.

So every line that does integer calculation ignoring overflow is wrong?
 
B

Ben Pfaff

Serve Laurijssen said:
So every line that does integer calculation ignoring overflow is wrong?

Yes. Unsigned integers don't overflow (they wrap around), but
signed integer overflow yields undefined behavior. Smart
compilers can depend on the undefinedness of signed integer
overflow for optimization purposes, causing your code to actually
malfunction if an overflow occurs.
 
K

Keith Thompson

Serve Laurijssen said:
So every line that does integer calculation ignoring overflow is wrong?

No. The code in question was a MIN macro, presumably intended to be
general-purpose. Ignoring overflow in such cases is a bad idea,
especially since it's easy enough to compute MIN in a way that avoids
overflow altogether. (The most straightforward implementation doesn't
work with operands with side effects -- so don't invoke it with
arguments with side effects.)
 
K

Kenneth Brody

Keith said:
Yes, it's cheating, because you're ignoring things like integer
overflow, loss of floating point precision, pointers, and so on.

Not to mention the fact that MAX() is probably still written using
the ?: operator.

What happens if you have a circular #define set? For example, if the
MAX() macro were also rewritten as above, referring to MIN()? My C
compiler expands MIN() by expanding MAX(), but leaving MAX's MIN()
intact. And MAX() expands MIN(), leaving its MAX() intact.

That is:

given:

#define MAX(x,y) ( (x)+(y) - MIN(x,y) )
#define MIN(x,y) ( (x)+(y) - MAX(x,y) )

then:

MIN(x,y)

expands to:

( (x)+(y) - ( (x)+(y) - MIN(x,y) ) )

Is this defined by the standard as such?

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <mailto:[email protected]>
 
B

Ben Pfaff

Kenneth Brody said:
What happens if you have a circular #define set? For example, if the
MAX() macro were also rewritten as above, referring to MIN()? My C
compiler expands MIN() by expanding MAX(), but leaving MAX's MIN()
intact. And MAX() expands MIN(), leaving its MAX() intact.

From C99 6.10.3.4 (similar text is in C90):

If the name of the macro being replaced is found during this
scan of the replacement list (not including the rest of the
source file's preprocessing tokens), it is not replaced.
Furthermore, if any nested replacements encounter the name
of the macro being replaced, it is not replaced. These
nonreplaced macro name preprocessing tokens are no longer
available for further replacement even if they are later
(re)examined in contexts in which that macro name
preprocessing token would otherwise have been replaced.
 

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

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top