ken*_*ytm 22
是的,你需要自己定义它.
void swap(void* a, void* b, size_t length),但不像std::swap,它不是类型安全的.inline关键字),这很重要.我们也可以定义一个宏
#define SWAP(a,b,type) {type ttttttttt=a;a=b;b=ttttttttt;}
Run Code Online (Sandbox Code Playgroud)
但它会影响ttttttttt变量,你需要重复它的类型a.(在gcc中有typeof(a)解决这个问题,但你仍然不能SWAP(ttttttttt,anything_else);.)
并且编写交换也不是那么困难 - 它只是3行简单的代码!
小智 13
C中没有等价物 - 事实上不可能,因为C没有模板功能.您必须为要交换的所有类型编写单独的函数.
如果你不介意使用C语言的gcc扩展,你可以用宏做类似的事情typeof:
#include <stdio.h>
#define SWAP(a, b) do { typeof(a) temp = a; a = b; b = temp; } while (0)
int main(void)
{
int a = 4, b = 5;
float x = 4.0f, y = 5.0f;
char *p1 = "Hello";
char *p2 = "World";
SWAP(a, b); // swap two ints, a and b
SWAP(x, y); // swap two floats, x and y
SWAP(p1, p2); // swap two char * pointers, p1 and p2
printf("a = %d, b = %d\n", a, b);
printf("x = %g, y = %g\n", x, y);
printf("p1 = %s, p2 = %s\n", p1, p2);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这在Clang和gcc中很快工作(但不是icc,它不能识别这个交换函数 - 但是,它会在任何标准C99编译器中编译),前提是优化实际上识别交换(它们在足够高的优化级别上执行) .
#include <string.h>
#define SWAP(a, b) swap_internal(&(a), &(b), sizeof *(1 ? &(a) : &(b)))
static inline void swap_internal(void *a, void *b, size_t size) {
char tmp[size];
memcpy(tmp, a, size);
memmove(a, b, size);
memcpy(b, tmp, size);
}
Run Code Online (Sandbox Code Playgroud)
现在解释它是如何工作的.首先,这SWAP()条线相对比较奇怪,但它实际上相对简单.&(a)是a作为指针传递的参数.同样,&(b)参数b作为指针传递.
最有趣的代码是sizeof *(1 ? &(a) : &(b)).这实际上是一个相对聪明的错误报告.如果不需要错误报告,那可能就是这样sizeof(a).三元运算符要求其运算具有兼容类型.在这种情况下,我通过将它们转换为指针来检查它们的类型兼容性的两个不同的参数(否则,int并且double将是兼容的).作为int *和double *不兼容,编译将失败...提供它的标准C编译器.遗憾的是,许多编译器void *在这种情况下假设类型,因此它失败了,但至少有一个警告(默认情况下启用).为了确保结果的正确大小,该值被解除引用并应用于sizeof,因此没有副作用.
~/c/swap $ gcc swap.c
swap.c: In function ‘main’:
swap.c:5:64: warning: pointer type mismatch in conditional expression [enabled by default]
#define SWAP(a, b) swap_internal(&(a), &(b), sizeof *(1 ? &(a) : &(b)))
^
swap.c:16:5: note: in expansion of macro ‘SWAP’
SWAP(cat, dog);
^
~/c/swap $ clang swap.c
swap.c:16:5: warning: pointer type mismatch ('int *' and 'double *') [-Wpointer-type-mismatch]
SWAP(cat, dog);
^~~~~~~~~~~~~~
swap.c:5:57: note: expanded from macro 'SWAP'
#define SWAP(a, b) swap_internal(&(a), &(b), sizeof *(1 ? &(a) : &(b)))
^ ~~~~ ~~~~
1 warning generated.
~/c/swap $ icc swap.c
swap.c(16): warning #42: operand types are incompatible ("int *" and "double *")
SWAP(cat, dog);
^
Run Code Online (Sandbox Code Playgroud)
这个宏只评估一次(sizeof特殊,因为它不评估它的参数).这可以提供安全性,例如array[something()].我能想到的唯一限制是它不能对register变量起作用,因为它依赖于指针,但除此之外,它是通用的 - 你甚至可以将它用于变长数组.它甚至可以处理交换相同的变量 - 而不是你想要这样做.