473,241 Members | 1,553 Online

# Avoiding name collisions in macros

Let's say I need to swap two int values frequently. I would write a macro:

#define swap(int a, int b) \
do { \
int temp = (a); \
(a) = (b); \
(b) = temp; \
} while (0)
Aside from the double evaluation of a and b, this works fine *except*
when either macro parameter a or b is called "temp." What's the best to
design macros to avoid these sort of collisions?

Is this a good candiate for using an identifier from that murky
legal-only-as-a-local-variable set, like _temp?

-Peter

(PS Yes, I know about various tricks with bitwise XOR, but I'm
interested in a general solution)

Nov 14 '05 #1
6 3840
In 'comp.lang.c', Peter Ammon <pe*********@rocketmail.com> wrote:
Let's say I need to swap two int values frequently. I would write a macro:

#define swap(int a, int b) \
Macro parameters have no type (or you mean 'inline').
Please don't retype, but copy and paste.

#define swap(a, b) \
do { \
int temp = (a); \
Hence, the macro name should be 'swap_int', or 'swap_i' or the like...
(a) = (b); \
(b) = temp; \
} while (0)

Aside from the double evaluation of a and b, this works fine *except*
when either macro parameter a or b is called "temp." What's the best to
design macros to avoid these sort of collisions?

Is this a good candiate for using an identifier from that murky
legal-only-as-a-local-variable set, like _temp?

I'm not sure it's legal, hence I prefer to postfix with '_'

#define swap(a_, b_) \
do { \
int temp_ = (a_); \
etc.

A little ugly, I concede...

--
-ed- get my email here: http://marreduspam.com/ad672570
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/
Nov 14 '05 #2

Emmanuel Delahaye wrote:
In 'comp.lang.c', Peter Ammon <pe*********@rocketmail.com> wrote:

Let's say I need to swap two int values frequently. I would write a macro:

#define swap(int a, int b) \ <snip>
Hence, the macro name should be 'swap_int', or 'swap_i' or the like...
If you're going to do that it's presumably because you have different
types you need to swap so you could just pass in the type as an argument
to one macro instead of creating several similair macros, e.g.:

#define swap(type,a,b) \
do { \
type _temp; \
...
<snip>Is this a good candiate for using an identifier from that murky
legal-only-as-a-local-variable set, like _temp?

Yes.

I'm not sure it's legal, hence I prefer to postfix with '_'

#define swap(a_, b_) \
do { \
int temp_ = (a_); \
etc.

A little ugly, I concede...

No need for the underscores on the parameters.

Ed.

Nov 14 '05 #3
Emmanuel Delahaye wrote:
In 'comp.lang.c', Peter Ammon <pe*********@rocketmail.com> wrote:

Let's say I need to swap two int values frequently. I would write a macro:

#define swap(int a, int b) \

Macro parameters have no type (or you mean 'inline').

Oops :)
Please don't retype, but copy and paste.
The code isn't actually C, but the general problem is. But since you

#define ASSIGN(a, b) do { id _temp = (a); (a)=[(b) retain]; [_temp
release]; } while (0)

#define ASSIGN_COPY(a, b) do { id _temp = (a); (a) = [(b) copy]; [_temp
release]; } while (0)

#define swap(a, b) \

do { \
int temp = (a); \

Hence, the macro name should be 'swap_int', or 'swap_i' or the like...

(a) = (b); \
(b) = temp; \
} while (0)

Aside from the double evaluation of a and b, this works fine *except*
when either macro parameter a or b is called "temp." What's the best to
design macros to avoid these sort of collisions?

Is this a good candiate for using an identifier from that murky
legal-only-as-a-local-variable set, like _temp?

I'm not sure it's legal, hence I prefer to postfix with '_'

#define swap(a_, b_) \
do { \
int temp_ = (a_); \
etc.

A little ugly, I concede...

--
Pull out a splinter to reply.
Nov 14 '05 #4
Groovy hepcat Peter Ammon was jivin' on Fri, 21 May 2004 11:54:41
-0700 in comp.lang.c.
Avoiding name collisions in macros's a cool scene! Dig it!
Let's say I need to swap two int values frequently. I would write a macro:

#define swap(int a, int b) \
do { \
int temp = (a); \
(a) = (b); \
(b) = temp; \
} while (0)

Aside from the double evaluation of a and b, this works fine *except*
when either macro parameter a or b is called "temp." What's the best to
design macros to avoid these sort of collisions?

Try creating some kind of Frankenstein's monster thingie with token
concatenation, maybe. Concatenate the names of the two macro arguments
together (and append or prepend temp or something to avoid the
resulting token being a keyword or something) and use the resulting
token as the variable's identifier. For example:

#include <stdio.h>

#define PASTE_(a, b) a ## b
#define PASTE(a, b) PASTE_(a, b)
#define SWAP(t, a, b) do{t PASTE(PASTE(a, b), temp) = (a); \
(a) = (b); \
(b) = PASTE(PASTE(a, b), temp);}while(0)

int main(void)
{
int x = 1, y = 9;

printf("x = %d, y = %d\n", x, y);
SWAP(int, x, y);
printf("x = %d, y = %d\n", x, y);

return 0;
}

--

Dig the even newer still, yet more improved, sig!

"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
Nov 14 '05 #5
Groovy hepcat Peter Ammon was jivin' on Fri, 21 May 2004 11:54:41
-0700 in comp.lang.c.
Avoiding name collisions in macros's a cool scene! Dig it!
Let's say I need to swap two int values frequently. I would write a macro:

#define swap(int a, int b) \
do { \
int temp = (a); \
(a) = (b); \
(b) = temp; \
} while (0)

Aside from the double evaluation of a and b, this works fine *except*
when either macro parameter a or b is called "temp." What's the best to
design macros to avoid these sort of collisions?

Try creating some kind of Frankenstein's monster thingie with token
concatenation, maybe. Concatenate the names of the two macro arguments
together (and append or prepend temp or something to avoid the
resulting token being a keyword or something) and use the resulting
token as the variable's identifier. For example:

#include <stdio.h>

#define PASTE_(a, b) a ## b
#define PASTE(a, b) PASTE_(a, b)
#define SWAP(t, a, b) do{t PASTE(PASTE(a, b), temp) = (a); \
(a) = (b); \
(b) = PASTE(PASTE(a, b), temp);}while(0)

int main(void)
{
int x = 1, y = 9;

printf("x = %d, y = %d\n", x, y);
SWAP(int, x, y);
printf("x = %d, y = %d\n", x, y);

return 0;
}

This technique only works if the second and third macro arguments are
identifiers. Otherwise, the pasting doesn't yield a valid preprocessor
token, e.g.

int a [] = {1, 9};
SWAP (int, a [0], a [1]);

doesn't work.

It also "pollutes" the namespace with `PASTE' and `PASTE_'. If that is
acceptable, why not go for the following much simpler solution:

#define SWAP(t, a, b) do { t PASTE = (a); \
(a) = (b); \
(b) = PASTE; } while (0)

Martin
--
,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
/ ,- ) http://www.zero-based.org/ ((_/)o o(\_))
\ `-' `-'(. .)`-'
`-. Debian, a variant of the GNU operating system. \_/
Nov 14 '05 #6
In article <news:cu*************@zero-based.org>
Martin Dickopp <ex****************@zero-based.org> writes:
[The token-pasting] technique [using the names of the variables
to be swapped] only works if the second and third macro arguments are
identifiers. Otherwise, the pasting doesn't yield a valid preprocessor
token, e.g.

int a [] = {1, 9};
SWAP (int, a [0], a [1]);

doesn't work.
Indeed.
It also "pollutes" the namespace with `PASTE' and `PASTE_'. If that is
acceptable, why not go for the following much simpler solution:

#define SWAP(t, a, b) do { t PASTE = (a); \
(a) = (b); \
(b) = PASTE; } while (0)

My usual method is just to write such swaps in-line, e.g., when
expanding a specialized sort function in C (in C++ one would just
use templates; and in Ada one would use generics, and so on; in
these languages the problem has a "language-preferred" solution).
If for some reason a swap macro appeals, one could perhaps do away
with the "type" parameter entirely, and supply instead a "temporary
variable" parameter:

#define SWAP(t, a, b) (t = (a), (a) = (b), (b) = t)
...
int a[N];
int swaptmp;
...
SWAP(swaptmp, a[i], a[j]); /* cf. SWAP(int, a[i], a[j]) */

In this version of the macro, I deliberately did not parenthesize
occurrences of the name "t" because it is supposed to be a simple
variable of the appropriate type.

If one wishes to reduce the scope of the variable to just the braces
introduced by a do-while(0) (e.g., to assist a compiler in
optimization) there is another variant of this method:

#define SWAP(t, v, a, b) \
do { t v = (a); (a) = (b); (b) = v; } while (0)
...
SWAP(int, swaptmp, a[i], a[j]);

So far, however, it has been my experience that compilers smart
enough to optimize swaps into machine-level XCHG instructions (or
equivalent) are also smart enough to do dataflow and lifetime
analysis on variables, so that they can already determine that
the "swaptmp" variable's value persists only for the one source
line.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603