宏交换(t,x,y)交换类型为t的两个参数
所以我基本上试图创建一个交换两个t类型参数的SWAP(t,x,y)宏。 当这两个参数都是这种forms时,我试图想到解决这个问题
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; }
什么想法可能会出错?
SWAP(int*, v[i++],w[f(x)]);
v[i++]
是一个int
元素,但是你将它分配给一个指针对象:
T *p = x;
所以你什么时候在T z = *p;
中取消引用T z = *p;
你得到一个段错误。 如果需要指向元素的指针,请使用&
运算符。
此外v[i++]
有副作用(它修改了i++
),你永远不应该传递在宏调用中有副作用的表达式。
#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)]);
该解决方案通过仅重新设置参数一次并通过重用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)