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

Macro that expand differently depending on the function calling it.

P: n/a
Hi,

Lets say I want to define a generic macro to swap bytes in a integer:
#define swapbytes(x) ...
I have several implementation of the macros, one is generic C, the
other one will be an optimized assembly version for a specific
architecture.

So I do something like that in swapbytes.h:

#ifdef __SOME_IMPLEMENTATION_SPECIFIC_MACRO__
#define swapbytes(x) \
... some implementation defined assembly crap...
#else
#define swapbytes(x) \
... some generic C code ...
#endif

This works well and I can extend this to support many different
implementation dependent optimizations: MIPS, ARM, x86,...

Now i have an additional issue. In some case, I have two functions in
the same source files that requires two different implementations of
the macro. An example of such case is when you deal with arm thumb or
mips16 instruction set. Some implementation allows you to mix both
types of code, but my swapbytes macro would needs to be different for
both of them.

Is there any way to handle that while still keeping a generic include
file ?

Thanks

-- Fabrice

PS: If you think this is off-topic because I mention mips16 and thumb,
dont even bother replying.I think the C standard was designed to cope
with implementation specific extensions and issues like this.

Oct 31 '07 #1
Share this Question
Share on Google+
12 Replies


P: n/a
On Wed, 31 Oct 2007 00:53:34 -0000, Fabrice
<fa*************@gmail.comwrote in comp.lang.c:
Hi,

Lets say I want to define a generic macro to swap bytes in a integer:
#define swapbytes(x) ...
I have several implementation of the macros, one is generic C, the
other one will be an optimized assembly version for a specific
architecture.

So I do something like that in swapbytes.h:

#ifdef __SOME_IMPLEMENTATION_SPECIFIC_MACRO__
#define swapbytes(x) \
... some implementation defined assembly crap...
#else
#define swapbytes(x) \
... some generic C code ...
#endif

This works well and I can extend this to support many different
implementation dependent optimizations: MIPS, ARM, x86,...

Now i have an additional issue. In some case, I have two functions in
the same source files that requires two different implementations of
the macro. An example of such case is when you deal with arm thumb or
mips16 instruction set. Some implementation allows you to mix both
types of code, but my swapbytes macro would needs to be different for
both of them.

Is there any way to handle that while still keeping a generic include
file ?

Thanks

-- Fabrice

PS: If you think this is off-topic because I mention mips16 and thumb,
dont even bother replying.I think the C standard was designed to cope
with implementation specific extensions and issues like this.
If you can provide proof from an Internationally recognized court of
law that has granted you supreme dictatorial powers over comp.lang.c,
and furthermore provide proof of that court's legal jurisdiction in
doing so, then you might attempt to forbid people who might dislike
your off-topic question from replying.

But I doubt if that would stop them. It certainly wouldn't stop me.

As for your incorrect belief about the C standard, and it is
incorrect, who gives a piece of bovine excrement?

*plonk*

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
Oct 31 '07 #2

P: n/a
Fabrice wrote:
Hi,

Lets say I want to define a generic macro to swap bytes in a integer:
#define swapbytes(x) ...
I have several implementation of the macros, one is generic C, the
other one will be an optimized assembly version for a specific
architecture.

So I do something like that in swapbytes.h:

#ifdef __SOME_IMPLEMENTATION_SPECIFIC_MACRO__
#define swapbytes(x) \
... some implementation defined assembly crap...
#else
#define swapbytes(x) \
... some generic C code ...
#endif

This works well and I can extend this to support many different
implementation dependent optimizations: MIPS, ARM, x86,...

Now i have an additional issue. In some case, I have two functions in
the same source files that requires two different implementations of
the macro. An example of such case is when you deal with arm thumb or
mips16 instruction set. Some implementation allows you to mix both
types of code, but my swapbytes macro would needs to be different for
both of them.
Why not just uses another macro, or better still, functions?

--
Ian Collins.
Oct 31 '07 #3

P: n/a
Fabrice <fabrice.gaut...@gmail.comwrote:
Lets say I want to define a generic macro to swap bytes
in a integer:
#define swapbytes(x) ...
I have several implementation of the macros, one is
generic C, the other one will be an optimized assembly
version for a specific architecture.

So I do something like that in swapbytes.h:

#ifdef __SOME_IMPLEMENTATION_SPECIFIC_MACRO__
#define swapbytes(x) \
... some implementation defined assembly crap...
#else
#define swapbytes(x) \
... some generic C code ...
#endif

This works well and I can extend this to support many
different implementation dependent optimizations: MIPS,
ARM, x86,...

Now i have an additional issue. In some case, I have two
functions in the same source files that requires two
different implementations of the macro.
So use two macros.

#define swapbytes_special(a,b) ...

#if blah
#define swapbytes(a,b) swapbytes_special(a,b)
#elif ...
#define swapbytes(a,b) ...
#elif ...
#define swapbytes(a,b) ...
....
#endif

void foo() { ...swapbytes_special(a,b); ... }
void bar() { ...swapbytes(a,b); ...}

<snip>
PS: If you think this is off-topic because I mention
mips16 and thumb, dont even bother replying.
If it's off topic, don't bother posting. That way,
everyone wins.
I think the C standard was designed to cope with
implementation specific extensions and issues like
this.
Of course it is. But that doesn't mean that comp.lang.c
is the place to discus those extensions.

--
Peter

Oct 31 '07 #4

P: n/a
Fabrice wrote:
Hi,

Lets say I want to define a generic macro to swap bytes in a integer:
#define swapbytes(x) ...
I have several implementation of the macros, one is generic C, the
other one will be an optimized assembly version for a specific
architecture.

So I do something like that in swapbytes.h:

#ifdef __SOME_IMPLEMENTATION_SPECIFIC_MACRO__
#define swapbytes(x) \
... some implementation defined assembly crap...
#else
#define swapbytes(x) \
... some generic C code ...
#endif

This works well and I can extend this to support many different
implementation dependent optimizations: MIPS, ARM, x86,...

Now i have an additional issue. In some case, I have two functions in
the same source files that requires two different implementations of
the macro. An example of such case is when you deal with arm thumb or
mips16 instruction set. Some implementation allows you to mix both
types of code, but my swapbytes macro would needs to be different for
both of them.

Is there any way to handle that while still keeping a generic include
file ?

Thanks

-- Fabrice

PS: If you think this is off-topic because I mention mips16 and thumb,
dont even bother replying.I think the C standard was designed to cope
with implementation specific extensions and issues like this.
#define swap(a,b) ((a)^=(b)^=(a)^=(b))
Doesn't get much simpler than that. Why do you need platform-specific
hoop-jumping?

--
Ark
Oct 31 '07 #5

P: n/a
Ark Khasin wrote:
#define swap(a,b) ((a)^=(b)^=(a)^=(b))
Doesn't get much simpler than that.
That expression is no good.

N869
6.5 Expressions
[#2] Between the previous and next sequence point an object
shall have its stored value modified at most once by the
evaluation of an expression.

--
pete
Oct 31 '07 #6

P: n/a
Ark Khasin <ak*****@macroexpressions.comwrites:
#define swap(a,b) ((a)^=(b)^=(a)^=(b))
Please read the FAQ.

3.3b: Here's a slick expression:

a ^= b ^= a ^= b

It swaps a and b without using a temporary.

A: Not portably, it doesn't. It attempts to modify the variable a
twice between sequence points, so its behavior is undefined.

For example, it has been reported that when given the code

int a = 123, b = 7654;
a ^= b ^= a ^= b;

the SCO Optimizing C compiler (icc) sets b to 123 and a to 0.

See also questions 3.1, 3.8, 10.3, and 20.15c.

(I don't endorse using products from SCO.)
--
Ben Pfaff
http://benpfaff.org
Oct 31 '07 #7

P: n/a
Ben Pfaff wrote:
Ark Khasin <ak*****@macroexpressions.comwrites:
>#define swap(a,b) ((a)^=(b)^=(a)^=(b))

Please read the FAQ.

3.3b: Here's a slick expression:

a ^= b ^= a ^= b

It swaps a and b without using a temporary.

A: Not portably, it doesn't. It attempts to modify the variable a
twice between sequence points, so its behavior is undefined.

For example, it has been reported that when given the code

int a = 123, b = 7654;
a ^= b ^= a ^= b;

the SCO Optimizing C compiler (icc) sets b to 123 and a to 0.

See also questions 3.1, 3.8, 10.3, and 20.15c.

(I don't endorse using products from SCO.)
OK. Got things wrong again. How about
#define swap(a,b) do{(a)^=(b); (b)^=(a); (a)^=(b);}while(0)
?
But all in all, I agree with FAQ 10.3: "If you're consumed by a
passionate desire to solve this problem once and for all, please
reconsider; there are better problems worthier of your energies."
--
Ark
Nov 1 '07 #8

P: n/a

# OK. Got things wrong again. How about
# #define swap(a,b) do{(a)^=(b); (b)^=(a); (a)^=(b);}while(0)

Assume for example, that variable a is loaded in register R1, and
b in R2. On optimising compiler can potentially translate:

t = a; a = b; b = t;

into the assembly code:

No code at all, it simply relabels register R2 as a and R1 as b.
An optimiser could possibly realizes the exclusive ors are a swap,
or it might not, with three operations to do what it might have done
with zero operations if the intent of the programmer was clear.

# But all in all, I agree with FAQ 10.3: "If you're consumed by a
# passionate desire to solve this problem once and for all, please
# reconsider; there are better problems worthier of your energies."

Let the optimiser worry about cleverness. Write code that is obvious.

--
SM Ryan http://www.rawbw.com/~wyrmwif/
You hate people.
But I love gatherings. Isn't it ironic.
Nov 1 '07 #9

P: n/a
Ark Khasin wrote:
>
.... snip ...
>
OK. Got things wrong again. How about
#define swap(a,b) do{(a)^=(b); (b)^=(a); (a)^=(b);}while(0)
?
But all in all, I agree with FAQ 10.3: "If you're consumed by a
passionate desire to solve this problem once and for all, please
reconsider; there are better problems worthier of your energies."
Fails. Try:

int a = 5;
swap(a, a);

results in a == 0

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
--
Posted via a free Usenet account from http://www.teranews.com

Nov 1 '07 #10

P: n/a
CBFalconer wrote:
Ark Khasin wrote:
... snip ...
>OK. Got things wrong again. How about
#define swap(a,b) do{(a)^=(b); (b)^=(a); (a)^=(b);}while(0)
?
But all in all, I agree with FAQ 10.3: "If you're consumed by a
passionate desire to solve this problem once and for all, please
reconsider; there are better problems worthier of your energies."

Fails. Try:

int a = 5;
swap(a, a);

results in a == 0
Arrgh! Which proves stealing is not good. Does FAQ 10.3 "If the values
are integers, a well-known trick using exclusive-OR could perhaps be
used" need revising?
--
Ark
Nov 1 '07 #11

P: n/a
Ark Khasin said:
CBFalconer wrote:
>Ark Khasin wrote:
... snip ...
>>OK. Got things wrong again. How about
#define swap(a,b) do{(a)^=(b); (b)^=(a); (a)^=(b);}while(0)
?
But all in all, I agree with FAQ 10.3: "If you're consumed by a
passionate desire to solve this problem once and for all, please
reconsider; there are better problems worthier of your energies."

Fails. Try:

int a = 5;
swap(a, a);

results in a == 0
Arrgh! Which proves stealing is not good. Does FAQ 10.3 "If the values
are integers, a well-known trick using exclusive-OR could perhaps be
used" need revising?
No, you just need to read it more carefully next time. It actually *tells*
you that the XOR "trick" doesn't work, in the very sentence you quote,
which reads in full as follows:

"If the values are integers, a well-known trick using exclusive-OR could
perhaps be used, but it will not work for floating-point values or
pointers, or if the two values are the same variable."

The whole thrust of FAQ 10.3 is "please don't do this stupid thing", and
anyone taking about 40% of *one* sentence of the reply out of context and
using it to justify or excuse broken code is guilty of reading with their
brain switched off.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Nov 1 '07 #12

P: n/a
Ark Khasin <ak*****@macroexpressions.comwrites:
Ben Pfaff wrote:
>Ark Khasin <ak*****@macroexpressions.comwrites:
>>#define swap(a,b) ((a)^=(b)^=(a)^=(b))
Please read the FAQ.
3.3b: Here's a slick expression:
a ^= b ^= a ^= b
It swaps a and b without using a temporary.
A: Not portably, it doesn't. It attempts to modify the variable a
twice between sequence points, so its behavior is undefined.
For example, it has been reported that when given the code
int a = 123, b = 7654;
a ^= b ^= a ^= b;
the SCO Optimizing C compiler (icc) sets b to 123 and a to 0.
See also questions 3.1, 3.8, 10.3, and 20.15c.
(I don't endorse using products from SCO.)
OK. Got things wrong again. How about
#define swap(a,b) do{(a)^=(b); (b)^=(a); (a)^=(b);}while(0)
?
[...]

Better, but still not good.

The "do { ... } while(0)" trick isn't needed in this case, since
everything in the expansion is just an expression (or would be if you
dropped the semicolons). You could just write:

#define swap(a,b) ((a)^=(b), (b)^=(a), (a)^=(b))

or, preferably:

#define SWAP(a,b) ((a)^=(b), (b)^=(a), (a)^=(b))

That does address the sequence-point issue.

But try using to swap floating-point variables. And it quietly fails
if you try to swap a variable with itself, something that could happen
accidentally if you do something like SWAP(array[i], array[j]) or
SWAP(*p1, *p2). Finally, it's not inconceivable that xor'ing two
signed integer values could do odd things on some systems (bitwise
operations on signed integers make me nervous).

The way to swap two variables is to use a temporary:

tmp = x;
x = y;
y = tmp;

This is simple enough that it's probably not worth the effort to
encapsulate it. Just write the three assignments where you need them.

(It would be nice if C allowed multiple values to be assigned, so you
could write something like ``(x, y) = (y, x)'', but it doesn't.)

--
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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Nov 1 '07 #13

This discussion thread is closed

Replies have been disabled for this discussion.