交换两个字符串指针

发布于 2024-09-24 23:48:25 字数 554 浏览 9 评论 0 原文

我必须在 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 系统上工作。

i have to char[] in C and i wanted to swap between them, by only swaping the pointer
to the array and not one char at a time so i wrote this code:

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

I get this output (note the last 4 characters)

abcdefgh8910
01234567ujk

When I expect:

abcdefghujk
012345678910

NOTE: I am working on a 64 bit Linux System.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

旧城空念 2024-10-01 23:48:25

您无法修改 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;
}

You can't modify the addresses of num1 and num2, your code should work if your test was instead:

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;
}
‖放下 2024-10-01 23:48:25

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

Arrays are not pointers. While they decay to pointers when you call your fastSwap(), these pointers are not the actual arrays. The fact that you need a cast should give you a hint that something is wrong.

This would work:

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);
聽兲甴掵 2024-10-01 23:48:25

这将起作用:

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

This will work:

int main ()
{
    char *num1 = "012345678910";
    char *num2 = "abcdefghujk";
    fastSwap (&num1,&num2);
    printf ("%s\n",num1);
    printf ("%s\n",num2);
    return 0;
}
时间海 2024-10-01 23:48:25

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

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

num1 is an array, and &num1 is the address of the array itself - it is not an address of a pointer.

The address of an array itself is the same location in memory as the address of the first element of the array, but it has a different type. When you cast that address to char **, you are claiming that it points at a char * value - but it does not. It points at a block of 13 chars. Your swap function then accesses that array of 13 chars as if it were a char * - since the latter is the same size as 8 chars on your platform, you end up swapping the first 8 chars of each array.

心房的律动 2024-10-01 23:48:25

你的 fastSwap 似乎只能工作。您通过将 '&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' then 是一个坏指针,但是因为它永远不会被取消引用,所以您可以避免崩溃/段错误。

因为您使用的是 64 位机器/操作系统指针是 8 个字节,所以“t”的值现在是“num2”的前 8 个字节,这就是之后放入 num1 的内容

*i = t

如果您打算交换指针,则必须首先创建像 Mark 那样的指针变量

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

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

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

Your fastSwap only seems to work. You're invoking undefined behavior by casting '&num1' and '&num2' (which are pointers to the characters of num1 and num2) to pointers to pointers of characters (char**).

char *t = *d

t will point to whatever d's contents are pointing to, however d is pointing to the actually characters of num2 ("abcdefghujk" or 0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x75 0x6B 0x00). This means that '*d' is actually copying the contents of 'num2' and not the pointer to num2 as you probably expected.

't' then is a bad pointer however since it is never dereferenced you avoid a crash/segment fault.

Because you're on a 64 bit machine/OS pointers are 8 bytes the value of 't' is now the first 8 bytes of 'num2' and this is what gets put into num1 after

*i = t

If you intend to swap pointers you must first create pointer variables as Mark did

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

Or change num1 and num2 into pointers (char *) rather than arrays (char[]) as sb1/Karl did

char *num1 = "012345678910";
char *num2 = "abcdefghujk";
fastSwap (&num1,&num2);
墟烟 2024-10-01 23:48:25

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

ps windows platform,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);
}

I've had the same situation and solved it with the following trick:

p.s. windows platform, 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);
}
岁吢 2024-10-01 23:48:25

将fastSwap改为:

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

      i ++;
      d ++;
   }
}

然后调用fastSwap(num1,num2);

Change fastSwap to:

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

      i ++;
      d ++;
   }
}

then call fastSwap (num1, num2);

后来的我们 2024-10-01 23:48:25
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);
}
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);
}
咿呀咿呀哟 2024-10-01 23:48:25

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

首先,您必须使用字符数组。应用 addressof 运算符不会给你一个指向指针的指针,而是一个指向数组的指针:

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

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

现在 fastSwap 中发生的情况是:

char* t = *d;

这会将 *d 的字节复制到 t 中,因为系统上的指针有大小。唯一:实际上,您没有指向指针的指针,而是指向仅已转换的数组的指针。因此 array 的前 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... 

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

While given answers already showed how to do it right (and hinted to undefined behaviour), you still might be interested in the details...

At very first, you have to character arrays. Applying the addressof operator to won't give you a pointer to pointer, but a pointer to array:

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

Syntax might look strange, but that's C. The important thing here now is: You have a pointer with one level of indirection. But you cast it to a pointer with two levels of indirection (char**).

What now happens in fastSwap is:

char* t = *d;

This will copy as many bytes of *d into t as pointers on your system have size. Solely: In reality, you do not have a pointer to pointer, but a pointer to array which only has been casted. So the first sizeof(void*) bytes of the array will be copied into t. Similarly for the other assignments, explaining the results you get.

If now your arrays were shorter than the size of pointers, then memory after the arrays would have been read:

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

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

would have printed on your system (as pointer size is 8 bytes):

456 789 456

Explanation:

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... 

Be aware that you don't have guarantee for such result, it is just the most likely one. You invoked undefined behaviour, anything might happen instead, you even might switch off the sun by accident (if your compiler happened to produce the appropriate code...).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文