-->

Macro SWAP(t,x,y) exchanging two arguments of type

2019-07-24 15:44发布

问题:

So I am basically trying to make a SWAP(t,x,y) macro that exchanges two arguments of type t. I am trying to think of going around the problem when these two arguments are of the form

v[i++] and w[f(x)] , i.e. SWAP(int, v[i++], w[f(x)]).

The code below is basically crashing ...

#define SWAP(T,x,y) {T *p = x; T *q = y; T z = *p; *p = *q; *q = z;}

int f (int x){
    return (0-x);
}

int main(void) {

int v[] = {1,2,3};
int i = 0;

int w[] = {4,5,6};
int x = -1;

int *p = v;
int *q = w;

SWAP(int*, v[i++],w[f(x)]);

return 0;
}

Any ideas what may go wrong?

回答1:

SWAP(int*, v[i++],w[f(x)]);

v[i++] is an int element but you are assigning it to a pointer object in:

T *p = x;

so when are you are dereferencing p in T z = *p; you get a segfault. If you want a pointer to the element use the & operator.

Moreover v[i++] has a side-effect (it modifies i++) and you should never pass expressions that have side-effects in a macro call.



回答2:

#define SWAP(T,x,y) {T *p = &(x); T *q = &(y); T z = *p; *p = *q; *q = z;}
...
    SWAP(int, v[i++], w[f(x)]);


回答3:

This solution avoids side-effects by only instansiating the argument once and shadowing by reusing SWAP as an identifier.

#define SWAP(type, a_, b_) \
do { \
    struct { type *a; type *b; type t; } SWAP; \
    SWAP.a  = &(a_); \
    SWAP.b  = &(b_); \
    SWAP.t  = *SWAP.a; \
    *SWAP.a = *SWAP.b; \
    *SWAP.b = SWAP.t; \
} while (0)