在C语言中,是否有不需要使用第三个变量就可以进行交换的内置交换函数?
不需要第三个变量就可以交换两个变量的值:
swap(first,second);
查看这里:http://www.cplusplus.com/reference/algorithm/swap/
a=a^b;
b=a^b;
a=b^a;
你也可以参考以下内容:
swap(&a, &a)
将无法工作。
2. 总的来说,速度较慢。 #define SWAP(x,y) do { \
typeof(x) _x = x; \
typeof(y) _y = y; \
x = _y; \
y = _x; \
} while(0)
swap(t[i++],i)
这样的技巧;为了避免它们,使用地址运算符&
。你最好使用临时变量(对于整数,有一个著名而无用的异或技巧)。_x
和 _y
(但我可以只使用一个本地变量)以便更好地阅读,并且也许可以使编译器进行更多优化。typeof(x) _tmp = x; x = y; y = _tmp;
)? - einpoklum在C语言中,没有标准的函数可以交换两个变量。
可以编写以下宏来实现:
#define SWAP(T, a, b) do { T tmp = a; a = b; b = tmp; } while (0)
宏可以这样调用:
int a = 42;
int b = 2718;
SWAP(int, a, b);
有一些编写SWAP宏的解决方案应该避免使用:
#define SWAP(a, b) do { a = b + a; b = a - b; a = a - b; } while (0)
当操作数为有符号类型时,可能会发生溢出,有符号溢出是未定义的行为。
此外,应避免尝试优化XOR解决方案的解决方案:
#define SWAP(a, b) (a ^= b ^= a ^=b)
a
在前一个序列点和下一个序列点之间被修改了两次,因此它违反了序列点规则且是未定义的行为。
typeof(expr)
这样的GCC扩展。 - user539810int
。现在我们可以说我们的所爱语言中有模板了 :-) - paxdiablo在C语言中,你可以将任何对象的表示形式复制到一个无符号字符数组中。以下宏允许您交换任何两个对象:
#define SWAP(X,Y) \
do { \
unsigned char _buf[sizeof(*(X))]; \
memmove(_buf, (X), sizeof(_buf)); \
memmove((X), (Y), sizeof(_buf)); \
memmove((Y), _buf, sizeof(_buf)); \
} while (0)
GCC在某些情况下甚至会为此生成最优代码。然而你可能会失去你的工作...
int x; double y;
? :-) 或许你的意思是同一类型的任意两个对象。 - paxdiablo有一个C++库函数,它可以交换两个整数变量的值。例如,swap(x, y); 将交换变量x和y的值。类似地,swap(mat[i][j], mat[j][i]); 将交换矩阵mat中的两个值,即第i行第j列的值和第j行第i列的值。
#define swap(T, x, y) \
{ \
T tmp = x; \
x = y; \
y = tmp; \
}
int main()
{
int a = 10;
int b = 20;
printf("a=%d b=%d\n", a, b);
swap(int, a, b);
printf("a=%d b=%d\n", a, b);
return 0;
}
虽然没有内置的交换函数,但你可以尝试以下方法:
a = a ^ b;
b = a ^ b;
a = b ^ a;
我相信我已经想出了一种类型无关的函数,可以在标准C中交换任何两个值,尽管由于我对这种语言还比较新,可能会有所忽略。它使用异或交换算法,我确信它可以进行更多优化,但只要这两个值指向由第三个参数指定的相同字节数,它就能正常工作:
void swapn(void *a, void *b, size_t n) {
if (a == b) {
return;
}
size_t i;
char *x = (char *)a,
*y = (char *)b;
for (i = 0; i < n; i++) {
*x ^= *y;
*y ^= *x;
*x ^= *y;
x++;
y++;
}
}
使用示例:
// swap two integers
int x = 5,
y = 30;
printf("%d\t%d\n", x, y);
swapn(&x, &y, sizeof(int));
printf("%d\t%d\n\n", x, y);
// swap two floats
float a = 9.23f,
b = 6.83f;
printf("%.2f\t%.2f\n", a, b);
swapn(&a, &b, sizeof(float));
printf("%.2f\t%.2f\n\n", a, b);
// swap two doubles
double p = 4.7539,
q = 0.9841;
printf("%.4f\t%.4f\n", p, q);
swapn(&p, &q, sizeof(double));
printf("%.4f\t%.4f\n\n", p, q);
// swap two chars
char m = 'M',
n = 'n';
printf("%c\t%c\n", m, n);
swapn(&m, &n, sizeof(char));
printf("%c\t%c\n\n", m, n);
// swap two strings of equivalent length
char s[] = "Hello",
t[] = "World";
printf("%s\t%s\n", s, t);
swapn(s, t, sizeof(s));
printf("%s\t%s\n\n", s, t);
输出结果为:
5 30
30 5
9.23 6.83
6.83 9.23
4.7539 0.9841
0.9841 4.7539
M n
n M
Hello World
World Hello
*x
。这很容易修复,但我不明白为什么要费心使用异或交换。它既不更快,也不更容易,在两个参数别名时会出错,在这个二十行的通用实现中,额外的变量甚至不是真正的更多代码。但它似乎相当类型不可知,我得承认这一点。n
应该是 size_t
。 - user395760
c=a; a=b; b=c;
这样工作。 - einpoklum