“正常”创建数组与使用malloc

时间:2019-07-24 21:41:32

标签: c arrays malloc

我把C指针弄糟了要学习的函数的指针。我创建了一个字符串数组,并希望在函数foo中使用指向指针的指针对其进行更改。然后我将其打印出来,仅供参考。

问题是:如果我“正常”创建它:char array[] = "yeah",则代码不起作用,并且在控制台上看到一堆奇怪的字符。但是,如果我使用malloc创建它,则可以使用。我真的很想了解区别。

这有效:

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

void foo(char **ptr);

int main(int argc, char *argv[]) {
    char *array = malloc(sizeof("yeah"));  //I need to malloc here, or it doesn't work. Why ?
    strcpy(array, "yeah");

    printf("array before : %s \n", array);

    char *ptr = array;
    char **pt = &ptr;

    foo(&array);

    printf("array after : %s \n", array);

    free(array);
}

void foo(char **ptr) {
    char *truc = malloc(sizeof(char) * 20);  //I need to malloc here, else it doesn't work. Why ?
    strcpy(truc, "then");

    *ptr = truc;
}

但这不是,它将在控制台上显示讨厌的字符:

void foo(char **ptr);

int main(int argc, char *argv[]) {
    char array[] = "yeah"; //created "normally"

    printf("array before : %s \n", array);

    char *ptr = array;
    char **pt = &ptr;

    foo(&array);

    printf("array after : %s \n", array);

    free(array);
}

void foo(char **ptr) {
    char truc = "then";

    *ptr = truc;
}

两者之间有什么区别

char array[] = "yeah";

char *array = malloc(sizeof("yeah");
strcpy(array, "yeah");

1 个答案:

答案 0 :(得分:2)

数组方式

首先要注意的是:代码char array[] = "yeah";可以使用。
注意:如果执行此操作,则不要调用free(array),因为它不是指向动态分配的内存的指针,并且不需要动态返回到堆。它存在于堆栈中。继续阅读...

但是这里的功能foo()是问题所在。调用foo()时,字符串truc(也可以声明为char truc[] = "then";)存在于堆栈帧中,该堆栈帧是程序存储器的一部分,仅存在到{{1} }返回。如果更改foo()指向该堆栈帧内的内存,则该函数返回时会发生什么?该堆栈帧变为未定义状态,您只能指向垃圾内存。

如果要更改array中字符串的内容,可以确保缓冲区足够长,并且array可以foo()进入缓冲区。因此,您无需更改指针本身,而只需更改其指向的内存即可。这不是我所谓的好的软件设计,但是为了举例,它对您有用。像这样:

strcpy(array, "then")

为什么没有void foo(char * ptr) { strcpy(ptr, "then"); } 中的malloc()也不起作用?

当您在main()中不要不要 malloc()时,main()表示一个数组。标识符本身不是指针,而是数组。但是,它会衰变为指针,或者,如果您愿意的话,它就像一个指针。这就是为什么您可以根据需要将其作为一个传递给您的原因,就像您将其传递给array一样。现在,如果您引用{em> foo()地址,例如array&array(char*)array&array一样-指向&array[0]开头的指针。在这种情况下,您的array实际上正在向foo()的内存中写入内存地址

这是做什么的?好吧,技术答案是不确定的行为。但是我猜想它正在将32位整数(一个内存地址)写入到一块内存中,该内存曾经代表一个字符串中的4个8位字符。所以现在您已经损坏了四个字符。而且,如果您显示的array正在使用foo(),也会引起内存泄漏。

它的巧妙之处在于您的字符串恰好是四个字符,因此这不会破坏字符串末尾的空终止符malloc()。让我猜,您看到的恰好是四个垃圾字符?