交换两个字符串指针

时间:2010-09-28 19:15:10

标签: c swap

我必须在C中使用char []并且我想通过仅交换指针来交换它们 到数组而不是一次只有一个char所以我写了这段代码:

#include <stdio.h>
void fastSwap (char **i, char **d)
{
    char *t = *d;
    *d = *i;
    *i = t;
}
int main ()
{
    char num1[] = "012345678910";
    char num2[] = "abcdefghujk";
    fastSwap ((char**)&num1,(char**)&num2);
    printf ("%s\n",num1);
    printf ("%s\n",num2);
    return 0;
}

我得到这个输出(注意最后4个字符)

abcdefgh8910
01234567ujk

当我期待:

abcdefghujk
012345678910

注意:我正在使用64位Linux系统。

9 个答案:

答案 0 :(得分:12)

您无法修改num1num2的地址,如果您的测试相反,您的代码应该有效:

int main ()
{
    char num1[] = "012345678910";
    char num2[] = "abcdefghujk";
    char *test1 = num1;
    char *test2 = num2;
    fastSwap (&test1,&test2);
    printf ("%s\n",test1);
    printf ("%s\n",test2);
    return 0;
}

答案 1 :(得分:7)

数组不是指针。当你调用fastSwap()时它们会衰减到指针,这些指针不是实际的数组。你需要演员表的事实应该给你一个错误的暗示。

这样可行:

void fastSwap (const char **i, const char **d)
{
    const char *t = *d;
    *d = *i;
    *i = t;
}

const char* num1 = "012345678910";
const char* num2 = "abcdefghujk";
fastSwap (&num1,&num2);
printf ("%s\n",num1);
printf ("%s\n",num2);

答案 2 :(得分:5)

这将有效:

int main ()
{
    char *num1 = "012345678910";
    char *num2 = "abcdefghujk";
    fastSwap (&num1,&num2);
    printf ("%s\n",num1);
    printf ("%s\n",num2);
    return 0;
}

答案 3 :(得分:4)

num1是一个数组,&num1是数组本身的地址 - 不是指针的地址。< / p>

数组本身的地址与内存中的第一个元素的地址位置相同,但它的类型不同。当您将该地址转换为char **时,您声称其指向char *值 - 但事实并非如此。它指向一个13个字符的块。然后你的交换函数访问13个字符的数组,好像它是char * - 因为后者与平台上的8 char大小相同,你最终交换每个字符的前8个字符阵列。

答案 4 :(得分:3)

你的fastSwap似乎才有用。您通过将'&amp; num1'和'&amp; num2'(指向num1和num2的字符的指针)转换为指向字符指针(char **)的指针来调用未定义的行为。

char *t = *d

t将指向任何内容指向的内容,但是d指向num2的实际字符(“abcdefghujk”或0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x75 0x6B 0x00)。这意味着'* d'实际上正在复制'num2'的内容,而不是像你预期的那样复制指向num2的指针。

然后

't'是一个坏指针,因为它永远不会被解除引用,你可以避免崩溃/段错误。

因为你在64位机器上/操作系统指针是8字节,'t'的值现在是'num2'的前8个字节,这是在

后放入num1的内容
*i = t

如果你打算交换指针,你必须首先创建指针变量,如Mark所做的那样

char *test1 = num1;
char *test2 = num2;
fastSwap (&test1,&test2);

或者将num1和num2更改为指针(char *)而不是数组(char []),如sb1 / Karl所做的那样

char *num1 = "012345678910";
char *num2 = "abcdefghujk";
fastSwap (&num1,&num2);

答案 5 :(得分:1)

我遇到了同样的情况并通过以下技巧解决了这个问题:

P.S。 Windows平台,vs-2012

void FastSwap (void **var1, void **var2) {
    void *pTmp = *var1;
    *var1 = *var2;
    *var2 = pTmp;
}

int main () {
    char *s1 = "1234567890123456";
    char *s2 = "abcdefghij";
    printf ("s1 before swap: \"%s\"\n", s1);
    printf ("s2 before swap: \"%s\"\n", s2);
    // if you change arguments in the FastSwap definition as (char **) 
    // then you can erase the (void **) part on the line below.
    FastSwap ((void **) &s1, (void **) &s2);
    printf ("s1 after swap : \"%s\"\n", s1);
    printf ("s2 after swap : \"%s\"\n", s2);
    return (0);
}

答案 6 :(得分:0)

将fastSwap更改为:

void fastSwap (char *i, char *d)
{
   while ((*i) && (*d))
   {
      char t = *d;
      *d = *i;
      *i = t;

      i ++;
      d ++;
   }
}

然后调用fastSwap(num1,num2);

答案 7 :(得分:0)

int swap(char *a, char *b){
    char *temp = (char *)malloc((strlen(a) + 1)*sizeof(char));
    strcpy(temp, a);
    strcpy(a, b);
    strcpy(b, temp);
}
int main(){
    char a[10] = "stack";
    char b[10] = "overflow";
    swap(a, b);
    printf("%s %s", a, b);
}

答案 8 :(得分:0)

尽管给出的答案已经显示了正确的操作方法(并提示行为未定义),但您仍然可能对详细信息感兴趣...

首先,您必须使用字符数组。将addressof运算符应用于不会提供指向指针的指针,而是指向数组的指针:

int(*ptr1)[10] = &num1;

语法可能看起来很奇怪,但这就是C。现在这里重要的是:您的指针具有一个间接级别。但是您将其强制转换为具有两个间接级别(char**)的指针。

fastSwap中现在发生的是:

char* t = *d;

这会将*d的字节复制到t中,这取决于系统上的指针大小。唯一的:实际上,您没有指向指针的指针,而是只有已强制转换的指向数组的指针。因此,数组的前sizeof(void*)个字节将被复制到t中。类似地,对于其他作业,说明您得到的结果。

如果现在您的数组小于指针的大小,则将读取数组之后的内存:

int a[] = "123";
int b[] = "456";
int c[] = "789";

fastSwap ((char**)&a, char**(&b));
printf("%s %s %s", a, b, c);

将在您的 系统上打印(指针大小为8个字节):

456 789 456

说明:

char *t = *d;
// copied the four bytes of b into t - AND the next four bytes (those of c!!!)

*d = *i;
// copied the eight bytes of a AND b int b AND c
// b contains "123", c "456"

*i = t;
// copied the eight bytes that were copied from b and c into a and b
// the "123" in b now got overwritten, that's why you never see them... 

请注意,您无法保证获得这种结果,这只是最有可能的结果。您调用了未定义的行为,可能发生任何事情,甚至可能偶然关闭了太阳(如果您的编译器碰巧产生了适当的代码...)。