C 交换两个字符串指针

C 交换两个字符串指针,c,swap,C,Swap,我必须在C中使用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";

我必须在C中使用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系统。

将fastSwap更改为:

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

      i ++;
      d ++;
   }
}
然后调用快速交换num1,num2

将fastSwap更改为:

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

      i ++;
      d ++;
   }
}

然后调用快速交换num1,num2

数组不是指针。当您调用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);

数组不是指针。当您调用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);

您不能修改num1和num2的地址,如果您的测试是:

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;
}

您不能修改num1和num2的地址,如果您的测试是:

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;
}
这将有助于:

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

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

您的快速交换似乎只起作用。您通过强制转换“&num1”和“&num2”来调用未定义的行为,这是指向num1字符的指针,而num2是指向char**字符指针的指针

char *t = *d
t将指向d的内容所指向的任何字符,但是d指向num2 abcdefghujk或0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x75 0x6B 0x00的实际字符。这意味着“*d”实际上是在复制“num2”的内容,而不是您可能期望的指向num2的指针

“t”则是一个错误的指针,但由于它从未被解除引用,因此可以避免崩溃/段故障

因为您在一台64位机器上/OS指针是8个字节,'t'的值现在是'num2'的前8个字节,这是之后放入num1的内容

*i = t
若你们想交换指针,你们必须首先像Mark那个样创建指针变量

char *test1 = num1;
char *test2 = num2;
fastSwap (&test1,&test2);
或者将num1和num2更改为指针char*,而不是像sb1/Karl那样的数组char[]

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

您的快速交换似乎只起作用。您通过强制转换“&num1”和“&num2”来调用未定义的行为,这是指向num1字符的指针,而num2是指向char**字符指针的指针

char *t = *d
t将指向d的内容所指向的任何字符,但是d指向num2 abcdefghujk或0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x75 0x6B 0x00的实际字符。这意味着“*d”实际上是在复制“num2”的内容,而不是您可能期望的指向num2的指针

“t”则是一个错误的指针,但由于它从未被解除引用,因此可以避免崩溃/段故障

因为您在一台64位机器上/OS指针是8个字节,'t'的值现在是'num2'的前8个字节,这是之后放入num1的内容

*i = t
若你们想交换指针,你们必须首先像Mark那个样创建指针变量

char *test1 = num1;
char *test2 = num2;
fastSwap (&test1,&test2);
或者将num1和num2更改为指针char*,而不是像sb1/Karl那样的数组char[]

char *num1 = "012345678910";
char *num2 = "abcdefghujk";
fastSwap (&num1,&num2);
num1是一个数组,&num1是数组本身的地址-它不是指针的地址

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

num1是一个数组,&num1是数组本身的地址——它不是指针的地址


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

我遇到了同样的情况,并用以下技巧解决了它:

p、 美国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);
}

我也遇到过同样的情况,并用以下技巧解决了它:

p、 美国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);
}

虽然给出的答案已经说明了如何正确操作,并暗示了未定义的行为,但您可能仍然对细节感兴趣

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

int(*ptr1)[10] = &num1;
语法可能看起来很奇怪,但这是C。现在重要的是:您有一个具有一级间接寻址的指针。但是你把它投射到一个有两个间接层次的指针上 r**

fastSwap中现在发生的情况是:

这将把*d的字节复制到t中,就像系统上的指针大小一样多。单独:实际上,您没有指向指针的指针,而是指向仅已强制转换的数组的指针。因此,数组的第一个sizeofvoid*字节将被复制到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... 

请注意,你不能保证这样的结果,它只是最有可能的一个。您调用了未定义的行为,任何事情都可能发生,如果您的编译器碰巧生成了适当的代码,您甚至可能会意外地关闭sun…

虽然给出的答案已经说明了如何正确执行,并暗示了未定义的行为,但您可能仍然对细节感兴趣

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

int(*ptr1)[10] = &num1;
语法可能看起来很奇怪,但这是C。现在重要的是:您有一个具有一级间接寻址的指针。但您将其转换为具有两级间接寻址字符**的指针

fastSwap中现在发生的情况是:

这将把*d的字节复制到t中,就像系统上的指针大小一样多。单独:实际上,您没有指向指针的指针,而是指向仅已强制转换的数组的指针。因此,数组的第一个sizeofvoid*字节将被复制到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... 


请注意,你不能保证这样的结果,它只是最有可能的一个。你调用了未定义的行为,任何事情都可能发生,如果你的编译器碰巧生成了合适的代码,你甚至可能会意外地关闭sun…

问题是什么?你的两个cast char**就是一个线索。当你对编译器撒谎时,它会惩罚你。一旦你让它工作起来,别忘了将它重命名为slowSwap。问题是什么?你的两个字符**就是一个线索。当你对编译器撒谎时,它会惩罚你。一旦你让它工作起来,别忘了将它重命名为slowSwap…并将它重命名为slowSwap。你真的编译并运行过它吗?我本以为指针的常数会出错。至少应该有一个警告,将常量字符**值传递给需要字符**的函数。@florin,@Mark,@caf:你说得对!我也不得不更改fastSwap功能,但我忘记了!现在添加了它。你真的编译并运行了它吗?我原以为指针的常量会出错。至少应该有一个警告,将常量字符**值传递给一个需要字符**的函数。@florin,@Mark,@caf:你说得对!我也不得不更改fastSwap功能,但我忘记了!现在添加。再看看他的输出。我也被愚弄了。@sbi源代码的问题是“指针”的交换实际上是交换数组的前8个字节,因为&num1是一个char*强制转换为char**。@bass-编译器将&num1视为“您想要一个指向char的指针”,但您强制它是指向char的指针。fastswap“char*t”的内部实际上是一个错误的指针,在64位little endian处理器上包含0x6162636465666768或0x6867666564636261。@bass:1你需要把你的…问题变成一个真正的问题。看到代码确实交换了,我想知道你在问什么。2回复评论时,您需要正确地@address people。事实上,梅里克永远不会看到你问他,除非他回来看看。3如果梅里克是对的,我相信他是对的,那么你在援引未定义的行为。所以你的代码实际上交换是偶然的。它也可以格式化你的硬盘。让数组变长,它的行为就会变得有趣。如果能深入了解为什么原始代码不起作用,而不仅仅是呈现固定的代码,这个答案会更有用。货运邪教就是这样开始的。再看看他的作品。我也被愚弄了。@sbi源代码的问题是“指针”的交换实际上是交换数组的前8个字节,因为&num1是一个char*强制转换为char**。@bass-编译器将&num1视为“您想要一个指向char的指针”,但您强制它是指向char的指针。fastswap“char*t”的内部实际上是一个错误的指针,在64位little endian处理器上包含0x6162636465666768或0x6867666564636261。@bass:1你需要把你的…问题变成一个真正的问题。看到代码确实
我想知道你在问什么。2回复评论时,您需要正确地@address people。事实上,梅里克永远不会看到你问他,除非他回来看看。3如果梅里克是对的,我相信他是对的,那么你在援引未定义的行为。所以你的代码实际上交换是偶然的。它也可以格式化你的硬盘。让数组变长,它的行为就会变得有趣。如果能深入了解为什么原始代码不起作用,而不仅仅是呈现固定的代码,这个答案会更有用。这就是cargo cults的入门方式。虽然此代码片段可能是解决方案,但确实有助于提高您的文章质量。请记住,您将在将来为读者回答这个问题,而这些人可能不知道您的代码建议的原因。我猜,如果您的交换函数主要有以下内容,您的交换函数将失败:char a[]=stack;字符b[]=溢出;虽然这个代码片段可能是解决方案,但它确实有助于提高文章的质量。请记住,您将在将来为读者回答这个问题,而这些人可能不知道您的代码建议的原因。我猜,如果您的交换函数主要有以下内容,您的交换函数将失败:char a[]=stack;字符b[]=溢出;