为了简要回答您的问题,就像其他答案已经说明的那样。 #ifdef/#ifndef 条件只关心宏标识符,因此参数不是其语法的一部分。
但是,您的宏有几个需要解决的弱点。首先,请注意,使用 XOR 运算符进行交换,虽然是避免使用临时变量的常用技巧,但如果两个参数是同一个对象,则会失败。这是因为第一个 XOR 的结果会是 0,剩下的 XOR 步骤无法恢复原始值。其次,这个版本的宏不能用于指针类型,因为 XOR 需要整数类型。第三,宏多次调用参数,如果参数是一个有副作用的表达式,就会出现问题。第四,宏中的复合语句应由do .. while (0) 保护,以允许宏扩展为语句。这使得宏在语法上更清晰,因此它后面的分号不是虚假的。
如单独答案中所述,在 C++ 中,使用 std::swap 而不是自己定义。不幸的是,C 没有提供通用的交换效用函数。但是,编写一个泛型函数并不难:
static inline void swap_generic (void *a, void *b, void *t, size_t sz) {
if (a != b) {
memcpy(t, a, sz);
memcpy(a, b, sz);
memcpy(b, t, sz);
}
}
然后您的宏可以调用此函数。
#ifndef SWAP
# ifdef __cplusplus
# define SWAP(a, b) std::swap(a, b)
# else
# define SWAP_ASSERT(X) _Static_assert(X, #X)
# if __STDC_VERSION__ < 201112L
# undef SWAP_ASSERT
# define SWAP_ASSERT(X) struct dummy
# endif
# define SWAP(a, b) do { \
SWAP_ASSERT(sizeof(a) == sizeof(b)); \
char t[sizeof(a) != sizeof(b) ? -1 : sizeof(a)]; \
swap_generic(&(a), &(b), t, sizeof(a)); \
} while (0)
# endif
#endif
如果检测到 C++,请注意我们如何使用 std::swap。
如果您使用支持 typeof 扩展的 C 编译器,那么宏可以大大简化,因为您不需要通用交换函数。
#ifndef SWAP
# ifdef __cplusplus
# define SWAP(a, b) std::swap(a, b)
# else
# define SWAP(a, b) do { \
typeof(a) *p = &(a), *q = &(b), t = *p; \
*p = *q; \
*q = t; \
} while (0)
# endif
#endif
请注意,typeof 版本提高了类型安全性。