首先你需要明白的是,当你把某个东西传递给一个函数时,这个东西会被复制到函数的参数中。
假设你有以下代码:
void swap1(int a, int b) {
int temp = a;
a = b;
b = temp;
assert(a == 17);
assert(b == 42);
}
int x = 42;
int y = 17;
swap1(x, y);
assert(x == 42);
assert(y == 17);
原始变量不会被交换,因为它们的值被复制到函数的参数中。然后函数继续交换这些参数的值,然后返回。原始值没有改变,因为函数只交换了自己的私有副本。
现在我们该如何解决这个问题呢?函数需要一种引用原始变量而不是它们的值副本的方法。在C语言中,我们如何引用其他变量?使用指针。
如果我们将指向变量的指针传递到函数中,函数可以交换“我们”的变量的值,��不是其自己的参数副本的值。
void swap2(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
assert(*a == 17);
assert(*b == 42);
}
int x = 42;
int y = 17;
swap2(&x, &y);
assert(x == 17);
assert(y == 42);
请注意,在函数内部,我们没有将值分配给指针,而是将其分配给它们所指向的内容。这些指针指向我们的变量
x
和
y
。该函数通过我们提供的指针直接更改了存储在
我们自己的变量中的值。这正是我们所需要的。
现在,如果我们有两个指针变量,并且想要交换
指针本身(而不是它们所指向的值),会发生什么情况?如果我们传递指针,那么指针将简单地被复制到参数中(而不是它们所指向的值)。
void swap3(int* a, int* b) {
int* temp = a;
a = b;
b = temp;
assert(*a == 17);
assert(*b == 42);
}
void swap4(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
assert(*a == 17);
assert(*b == 42);
}
int x = 42;
int y = 17;
int* xp = &x;
int* yp = &y;
swap3(xp, yp);
assert(xp == &x);
assert(yp == &y);
assert(x == 42);
assert(y == 17);
swap4(xp, yp);
assert(xp == &x);
assert(yp == &y);
assert(x == 17);
assert(y == 42);
函数
swap3
只交换其参数中得到的指针的私有副本。这与
swap1
存在相同的问题。而
swap4
改变了我们的变量所指向的值,而不是指针!我们给函数提供了一种引用变量
x
和
y
的方法,但我们希望它们引用
xp
和
yp
。
我们如何做到这一点?我们传递它们的地址!
void swap5(int** a, int** b) {
int* temp = *a;
*a = *b;
*b = temp;
assert(**a == 17);
assert(**b == 42);
}
int x = 42;
int y = 17;
int* xp = &x;
int* yp = &y;
swap5(&xp, &yp);
assert(xp == &y);
assert(yp == &x);
assert(x == 42);
assert(y == 17);
这样它就交换了我们的指针变量(注意现在
xp
指向
y
),但没有交换它们所指向的值。我们为它提供了一种引用我们的指针变量的方式,因此它可以更改它们!
现在应该很容易理解如何交换两个以
char*
变量形式表示的字符串。交换函数需要接收
char*
指针。
void swapStrings(char** a, char** b){
char *temp = *a;
*a = *b;
*b = temp;
assert(strcmp(*a, "world") == 0);
assert(strcmp(*b, "Hello") == 0);
}
char* x = "Hello";
char* y = "world";
swapStrings(&x, &y);
assert(strcmp(x, "world") == 0);
assert(strcmp(y, "Hello") == 0);