关于以下代码的两个问题:
有和没有malloc()声明之间有什么区别:
p = (char *) malloc (20 * sizeof(char) );
Run Code Online (Sandbox Code Playgroud)
它只是内存位置的差异吗?指针变量' p'在没有该语句的STACK中,在HEAP中有该语句?
为什么陈述是
printf("%s\n", p);
Run Code Online (Sandbox Code Playgroud)
不
printf("%s\n", *p);
Run Code Online (Sandbox Code Playgroud)#include <stdlib.h>
#include <stdio.h>
int main () {
char movie[] = "forrest gump";
char *p;
p = (char *) malloc (20 * sizeof(char) );
p = movie;
printf("%p\n", p);
printf("%p\n", movie);
printf("%s\n", p); // to print "forrest gump"
free(p);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
添加了行号注释的代码:
char movie[] = "forrest gump"; // 1
char *p; // 2
p = (char *) malloc (20 * sizeof(char) ); // 3
p = movie; // 4
printf("%p\n", p); // 5
printf("%p\n", movie); // 6
printf("%s\n", p); // to print "forrest gump" // 7
free(p); // 8
Run Code Online (Sandbox Code Playgroud)
我将忽略malloc()没有检查返回值,malloc()并且只要你的编译器告诉你,如果你省略声明的话,我就不会对返回值的强制转换进行分阶段malloc()- 但是有很多人会不同意.这* sizeof(char)不是必要的,可能写得更好* sizeof(*p).
代码有内存泄漏,由于内存泄漏,它表现出未定义的行为.
1号线很好.第2行同样很好,但可以通过将变量与第3行组合来初始化变量.
在这种情况下,第3行是安全的,但是在其他情况下,分配的固定大小将是一个问题.
第4行是一个主要问题.这是泄漏.你只是践踏了返回的内存的唯一指针malloc(),因此内存不可避免地丢失了.当然,这个程序将很快退出(如果它没有先崩溃),但总的来说,这很糟糕.你应该写的:
strcpy(p, movie);
Run Code Online (Sandbox Code Playgroud)
也许:
memmove(p, movie, sizeof(movie));
Run Code Online (Sandbox Code Playgroud)
第5行将打印存储的地址p.如上所述,这是movie因为第4行中的赋值的地址.可以说,它应该使用强制转换来编写,因为%p格式说明符采用void *:
printf("%p\n", (void *)p);
Run Code Online (Sandbox Code Playgroud)
在实践中,您会在摆脱它到处p是char *.我学会了在机器上编程(在有C标准的前几天),其中char *地址的位表示anything_bigger *与同一存储位置的地址不同.在这样的机器上,如果代码处理struct Something *甚至是int *,则void *需要使用强制转换.
第6行产生与第5行相同的输出,并具有相同的警告.
第7行很好,打印出p指向的数据,这也是movie指向的数据.
第8行是调用未定义行为的地方.由于第4行的任务,你试图释放未分配的空间,这是一场严重的灾难.它经常会导致崩溃; 这绝不是一个好主意.
代码应该合理地读取:
char movie[] = "forrest gump";
char *p = malloc(sizeof(movie)); // or: char *p = malloc(strlen(movie) + 1);
if (p != 0)
{
strcpy(p, movie);
printf("%p\n", p);
printf("%p\n", movie);
printf("%s\n", p);
free(p);
}
Run Code Online (Sandbox Code Playgroud)
你的问题2是关于:
printf("%s\n", p);
printf("%s\n", *p);
Run Code Online (Sandbox Code Playgroud)
第一个是正确的. p是一个char *,%s转换规范期望a char *.第二个是不正确的,因为*p是a char,但%s期望a char *.相反,它会获得一个小整数(如果您的代码集基于ASCII,则为102)并尝试将其视为地址.这不起作用; 它通常会导致崩溃,因为整个第一页内存(1 KiB或4 KiB)通常被映射为无效.
你可以使用:
printf("%c\n", *p);
Run Code Online (Sandbox Code Playgroud)
哪个会打印f.