在C中交换指针(char,int)

当我在C中交换指针时,我一直在努力理解不同的行为。如果我想交换两个int指针,那么我可以做

 void intSwap (int *pa, int *pb){ int temp = *pa; *pa = *pb; *pb = temp; } 

但是,如果我想交换两个char指针,我需要做类似的事情

 void charSwap(char** a, char** b){ char *temp = *a; *a = *b; *b = temp; } 

因为如果我这样做

 void charSwap(char* a, char* b){ char temp = *a; *a = *b; *b = temp; } 

编译器抱怨表达式* a = * b,因为它无法更改值。 如果我想交换两个strings (即char* s1= "Hello"; char* s2="Bye"; )怎么会这样做?

你能给我一点帮助吗? 我想真正了解它是如何工作的,所以在获得正确答案之前我不需要经历反复试验。 我希望它对许多其他人有用。

您需要了解的第一件事是,当您将某些内容传递给函数时,会将某些内容复制到函数的参数中。

假设您有以下内容:

 void swap1(int a, int b) { int temp = a; a = b; b = temp; assert(a == 17); assert(b == 42); // they're swapped! } int x = 42; int y = 17; swap1(x, y); assert(x == 42); assert(y == 17); // no, they're not swapped! 

原始变量不会被交换,因为它们的值被复制到函数的参数中。 然后函数继续交换这些参数的值,然后返回。 原始值不会更改,因为该function仅交换其自己的私有副本。

现在我们如何解决这个问题? 该函数需要一种方法来引用原始变量,而不是它们的值的副本。 我们怎样才能引用C中的其他变量? 使用指针。

如果我们将指向变量的指针传递给函数,函数可以交换变量中的值,而不是它自己的参数副本。

 void swap2(int* a, int* b) { int temp = *a; *a = *b; *b = temp; assert(*a == 17); assert(*b == 42); // they're swapped! } int x = 42; int y = 17; swap2(&x, &y); // give the function pointers to our variables assert(x == 17); assert(y == 42); // yes, they're swapped! 

注意函数内部我们没有分配指针,而是指定它们指向的内容。 指针指向我们的变量xy 。 该函数通过我们给出的指针直接改变存储在变量中的值。 而这正是我们所需要的。

现在如果我们有两个指针变量并希望交换指针本身(而不是它们指向的值)会发生什么? 如果我们传递指针,指针将被简单地复制(而不是它们指向的值)到参数。

 void swap3(int* a, int* b) { int* temp = a; a = b; b = temp; assert(*a == 17); assert(*b == 42); // they're swapped! } void swap4(int* a, int* b) { int temp = *a; *a = *b; *b = temp; assert(*a == 17); assert(*b == 42); // they're swapped! } 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); // Didn't swap anything! swap4(xp, yp); assert(xp == &x); assert(yp == &y); assert(x == 17); assert(y == 42); // Swapped the stored values instead! 

函数swap3只交换它在参数中获得的指针的私有副本。 这与swap1问题相同。 而且swap4正在改变变量指向的值,而不是指针! 我们给函数一个引用变量xy但我们希望它们引用xpyp

我们怎么做? 我们传递他们的地址!

 void swap5(int** a, int** b) { int* temp = *a; *a = *b; *b = temp; assert(**a == 17); assert(**b == 42); // they're swapped! } 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); // swapped only the pointers variables 

这样它会交换我们的指针变量(注意xp现在指向y ),但不是它们指向的值。 我们给它一个方法来引用我们的指针变量,所以它可以改变它们!

到现在为止,应该很容易理解如何以char*变量的forms交换两个字符串。 swap函数需要接收指向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); 
 void intSwap (int *pa, int *pb){ int temp = *pa; *pa = *pb; *pb = temp; } 

你需要知道以下内容 –

 int a = 5; // an integer, contains value int *p; // an integer pointer, contains address p = &a; // &a means address of a a = *p; // *p means value stored in that address, here 5 

 void charSwap(char* a, char* b){ char temp = *a; *a = *b; *b = temp; } 

所以,当你像这样交换。 只交换该值。 因此,对于char*只有他们的第一个char才会交换。

现在,如果你清楚地理解char *(字符串),那么你应该知道,你只需要交换指针。 如果你认为它是一个array而不是字符串,这将更容易理解。

 void stringSwap(char** a, char** b){ char *temp = *a; *a = *b; *b = temp; } 

所以,这里你传递的是双指针,因为array本身就是一个指针。

在C中,如您所知,字符串是字符指针(char *)。 如果要交换两个字符串,则需要交换两个char指针,即只有两个地址。 为了在函数中进行任何交换,您需要为其提供要交换的两件事的地址。 因此,在交换两个指针的情况下,您需要一个指向指针的指针。 非常喜欢交换int,你只需要一个指向int的指针。

你的最后一个代码片段不起作用的原因是因为你期望它交换两个char指针 – 它实际上被写为交换两个字符!

编辑:在上面的例子中,你正试图错误地交换两个int指针,正如R. Martinho Fernandes所指出的那样。 如果您有以下情况,那将换掉两个整数:

 int a, b; intSwap(&a, &b); 

您需要了解pass-by-reference和pass-by-value之间的差异。

基本上,C只支持按值传递。 因此,在将变量传递给函数时,不能直接引用变量。 如果要将变量更改为交换所执行的函数,则需要使用pass-by-reference。 要在C中实现pass-by-reference,需要使用指针,它可以取消引用该值。

function:

 void intSwap(int* a, int* b) 

它将两个指针值传递给intSwap,并在函数中交换a / b指向的值,但不交换指针本身。 这就是R. Martinho和Dan Fego说它交换两个整数而不是指针的原因。

对于字符,我认为你的意思是字符串,更复杂。 C中的字符串实现为chars数组,由char *引用,指针作为字符串值。 如果你想通过引用传递char *,你需要使用char *的ponter,所以你得到char **。

也许下面的代码更清楚:

 typedef char* str; void strSwap(str* a, str* b); 

语法swap(int&a,int&b)是C ++,它直接表示pass-by-reference。 也许一些C编译器也实现了。

希望我能说得更清楚,而不是满足。

如果您有使用C ++的奢侈,请使用:

 template void swapPrimitives(T& a, T& b) { T c = a; a = b; b = c; } 

当然,在char*的情况下,它只会交换指针本身,而不是它们指向的数据,但在大多数情况下,这没关系,对吧?