Connecting Tech Pros Worldwide Help | Site Map

Avoiding name collisions in macros

Peter Ammon
Guest
 
Posts: n/a
#1: Nov 14 '05
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?

Thanks for your thoughts,
-Peter

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

Emmanuel Delahaye
Guest
 
Posts: n/a
#2: Nov 14 '05

re: Avoiding name collisions in macros


In 'comp.lang.c', Peter Ammon <peter_ammon@rocketmail.com> wrote:
[color=blue]
> Let's say I need to swap two int values frequently. I would write a macro:
>
> #define swap(int a, int b) \[/color]

Macro parameters have no type (or you mean 'inline').
Please don't retype, but copy and paste.

#define swap(a, b) \
[color=blue]
> do { \
> int temp = (a); \[/color]

Hence, the macro name should be 'swap_int', or 'swap_i' or the like...
[color=blue]
> (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?[/color]

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
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=c99
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/
Ed Morton
Guest
 
Posts: n/a
#3: Nov 14 '05

re: Avoiding name collisions in macros




Emmanuel Delahaye wrote:[color=blue]
> In 'comp.lang.c', Peter Ammon <peter_ammon@rocketmail.com> wrote:
>
>[color=green]
>>Let's say I need to swap two int values frequently. I would write a macro:
>>
>>#define swap(int a, int b) \[/color][/color]
<snip>[color=blue]
> Hence, the macro name should be 'swap_int', or 'swap_i' or the like...[/color]

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>[color=blue][color=green]
>>Is this a good candiate for using an identifier from that murky
>>legal-only-as-a-local-variable set, like _temp?[/color][/color]

Yes.
[color=blue]
>
> 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...[/color]

No need for the underscores on the parameters.

Ed.

Peter Ammon
Guest
 
Posts: n/a
#4: Nov 14 '05

re: Avoiding name collisions in macros


Emmanuel Delahaye wrote:[color=blue]
> In 'comp.lang.c', Peter Ammon <peter_ammon@rocketmail.com> wrote:
>
>[color=green]
>>Let's say I need to swap two int values frequently. I would write a macro:
>>
>>#define swap(int a, int b) \[/color]
>
>
> Macro parameters have no type (or you mean 'inline').[/color]

Oops :)
[color=blue]
> Please don't retype, but copy and paste.[/color]

The code isn't actually C, but the general problem is. But since you
asked...

#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)
[color=blue]
>
> #define swap(a, b) \
>
>[color=green]
>> do { \
>> int temp = (a); \[/color]
>
>
> Hence, the macro name should be 'swap_int', or 'swap_i' or the like...
>
>[color=green]
>> (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?[/color]
>
>
> 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...
>[/color]


--
Pull out a splinter to reply.
Peter Shaggy Haywood
Guest
 
Posts: n/a
#5: Nov 14 '05

re: Avoiding name collisions in macros


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!
[color=blue]
>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?[/color]

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!

http://alphalink.com.au/~phaywood/
"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"?
Martin Dickopp
Guest
 
Posts: n/a
#6: Nov 14 '05

re: Avoiding name collisions in macros


phaywood@alphalink.com.au.NO.SPAM (Peter "Shaggy" Haywood) writes:
[color=blue]
> 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!
>[color=green]
>>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?[/color]
>
> 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;
> }[/color]

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. \_/
Chris Torek
Guest
 
Posts: n/a
#7: Nov 14 '05

re: Avoiding name collisions in macros


In article <news:cunr7tbfk18.fsf@zero-based.org>
Martin Dickopp <expires-2004-06-30@zero-based.org> writes:[color=blue]
>[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.[/color]

Indeed.
[color=blue]
>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)[/color]

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
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Closed Thread