C:字符串的malloc显示带有双指针和函数调用的意外行为

问题描述 投票:0回答:1

这是一个查询,以了解以下代码即使有错误也能正常工作。

据我所知,如果我想重新分配/重新分配传递给函数的指针,则该指针需要作为双指针传递。错误地,我传递了一个指针,程序仍在工作。我猜想它必须在指针是字符串的情况下执行某些操作。

程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void func2( char **x){

    printf("befor func2 x = %u; *x = %u; **x = %s; x_size = %u\n", x, *x, *x, strlen(*x));
    free(*x);
    *x = (char *)malloc(20);
    strcpy(*x, "zyxwvutsrqponmlkjih");

    printf("\n\nafter func2 x = %u; *x = %u; **x = %s; x_size = %u\n", x, *x, *x, strlen(*x));
}

void func1( char *x){

    printf("befor func1 &x = %u; x = %u; *x = %s; x_size = %u \n", &x, x, x, strlen(x));
    func2(&x);
    printf("after func1 &x = %u; x = %u; *x = %s; x_size = %u \n", &x, x, x, strlen(x));
}

int main(){

    char *x; 
    x = (char *)malloc(10);
    strcpy(x, "abcdefghi");
    printf("befor  main &x = %u; x = %u; x = %s; x_size = %u\n", &x, x, x, strlen(x));
    func1(x);
    printf("after  main &x = %u; x = %u; x = %s; x_size = %u\n", &x, x, x, strlen(x));
    free(x);
    return 1;
}

输出:

befor  main &x = 489275896; x = 20414480; x = abcdefghi; x_size = 9
befor func1 &x = 489275864; x = 20414480; *x = abcdefghi; x_size = 9 
befor func2 x = 489275864; *x = 20414480; **x = abcdefghi; x_size = 9


after func2 x = 489275864; *x = 20414480; **x = zyxwvutsrqponmlkjih; x_size = 19
after func1 &x = 489275864; x = 20414480; *x = zyxwvutsrqponmlkjih; x_size = 19 
after  main &x = 489275896; x = 20414480; x = zyxwvutsrqponmlkjih; x_size = 19

我可以理解直到func1为止的输出。但是在main中进行修改后,大小和值如何返回到func2?我没有将x作为双指针从main传递到func1。但是不知何故它仍在工作。是因为它是char *吗?

编辑1:

在注释中建议的编辑后:

程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void func2( char **x){

    printf("befor func2 x = %p; *x = %p; **x = %s; x_size = %u\n", x, *x, *x, strlen(*x));
    free(*x);
    *x = (char *)malloc(20);
    strcpy(*x, "zyxwvutsrqponmlkjih");

    printf("\n\nafter func2 x = %p; *x = %p; **x = %s; x_size = %u\n", x, *x, *x, strlen(*x));
}

void func1( char *x){

    printf("befor func1 &x = %p; x = %p; *x = %s; x_size = %u \n", &x, x, x, strlen(x));
    func2(&x);
    printf("after func1 &x = %p; x = %p; *x = %s; x_size = %u \n", &x, x, x, strlen(x));
}

int main(){

    char *x, *y, *z; 
    x = (char *)malloc(10);
    z = (char *)malloc(100);
    y = (char *)malloc(100);
    strcpy(x, "abcdefghi");
    printf("befor  main &x = %p; x = %p; x = %s; x_size = %u\n", &x, x, x, strlen(x));
    func1(x);
    printf("after  main &x = %p; x = %p; x = %s; x_size = %u\n", &x, x, x, strlen(x));
    free(x);
    free(y);
    free(z);
    return 1;
}

输出:

befor  main &x = 0x7fff78cb09c8; x = 0x1c7a010; x = abcdefghi; x_size = 9
befor func1 &x = 0x7fff78cb09a8; x = 0x1c7a010; *x = abcdefghi; x_size = 9 
befor func2 x = 0x7fff78cb09a8; *x = 0x1c7a010; **x = abcdefghi; x_size = 9


after func2 x = 0x7fff78cb09a8; *x = 0x1c7a010; **x = zyxwvutsrqponmlkjih; x_size = 19
after func1 &x = 0x7fff78cb09a8; x = 0x1c7a010; *x = zyxwvutsrqponmlkjih; x_size = 19 
after  main &x = 0x7fff78cb09c8; x = 0x1c7a010; x = zyxwvutsrqponmlkjih; x_size = 19

[程序在引入多个malloc之后仍然可以工作。

c string pointers malloc double-pointer
1个回答
0
投票

您似乎认为使用char *x(单个指针)作为func1的参数是一个错误。但是,我认为这很好。 func1期望将char指针作为参数,或者基本上是将其取消引用时给出char或一堆char的内存地址。当您在main中写入func1(x);时,您正在传递x,即一堆字符的地址,这正是参数func1所期望的类型。

为什么x是一堆字符的地址?在这种情况下,指针x正在存储(字符)数组的地址。现在,您可能知道,如果只写一个数组的名称,就可以得到该数组的基地址。参见下面的代码:

#include <stdio.h>
#include <stdlib.h>

int main () {
    int arr[5] = {1, 2, 3, 4, 5};
    printf ("%d\n", arr);       // address of the first element (1) of the array
                                // or, the base address of the array
    printf ("%d\n", &arr[0]);   // same as above
    printf ("%d\n\n", *arr);      // gives the first element of the array

    int *x = malloc (5*sizeof (int));
    *x = 1;
    *(x+1) = 2;
    *(x+2) = 3;
    *(x+3) = 4;
    *(x+4) = 5;
    printf ("%d\n", x);        // address of the first element (1) of the array
                               // or, the base address of the array
    printf ("%d\n", &*(x+0));  // same as above
    printf ("%d\n\n", *x);     // gives the first element of the array
    return 0;
}

输出如下:

6356712
6356712
1

9768168
9768168
1

现在,为什么我们能够修改x指向的字符数组中的值?因为我们已经传递了该数组的基地址。我们可以取消引用该地址以访问该数组并对其执行任何操作。

© www.soinside.com 2019 - 2024. All rights reserved.