我把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");
答案 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()
。让我猜,您看到的恰好是四个垃圾字符?