2013-05-04 89 views
1

所以我基本上试图做一个交换两个t类型参数的SWAP(t,x,y)宏。我试图考虑当这两个参数的形式为宏SWAP(t,x,y)交换t类型的两个参数

v [i ++]和w [f(x)],即SWAP(int,v [i ++],w [f(x) )])。

下面的代码基本上是崩溃......

#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; 
} 

任何想法可能会错呢?

回答

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

v[i++]int元素,但你是在分配给一个指针对象:

T *p = x; 

所以当你解引用pT z = *p;你得到一个段错误。如果你想要一个指向元素的指针,使用&运算符。

此外v[i++]有一个副作用(它修改i++),你不应该通过在宏调用中有副作用的表达式。

+0

谢谢。现在一切都好!这个“副作用”问题是我想要解决的真正问题。 – Rayhunter 2013-05-04 18:56:44

+0

请downvoter,解释你downvote。 – ouah 2013-05-05 01:59:24

+0

如果其中任何一个参数都是'p' - 这将失败(但我的投票不过)。下面包括自己的答案。 – ideasman42 2015-03-27 15:10:56

3
#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)]); 
+0

是的,正好:) – Rayhunter 2013-05-04 22:44:55

+1

如果可能,最好引用宏参数名:'#define SWAP(T,x,y){T * p =&(x),* q =&(y),z = * p; * p = * q; * q = z; }'。这减少了宏的文本替换与C语法交互时发生的错误。 – 2013-05-05 12:50:09

+0

@EricPostpischil这是一个好点,因为结果可能因操作符优先级而异。 它已修复。谢谢。 – BLUEPIXY 2013-05-05 13:06:17

0

将该溶液通过仅一次instansiating参数和通过重用SWAP作为标识符遮蔽避免副作用。

#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)