【 C 】动态内存分配案例分析

举报
李锐博恩 发表于 2021/07/15 05:57:48 2021/07/15
【摘要】 声明一个指向char类型的指针,可以在声明的时候就对其进行初始化,这样是合理的。 例如: E1: #include <stdio.h>#include <stdlib.h>#include <string.h> int main(){ char name[100]; char *description = "Zara ali ...

声明一个指向char类型的指针,可以在声明的时候就对其进行初始化,这样是合理的。

例如:

E1:


  
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. int main()
  5. {
  6. char name[100];
  7. char *description = "Zara ali a DSP student in class 10th.";
  8. strcpy(name, "Zara Ali");
  9. printf("Name = %s\n", name );
  10. printf("Description: %s\n", description );
  11. }

运行结果:


  
  1. $gcc -o main *.c
  2. $main
  3. Name = Zara Ali
  4. Description: Zara ali a DSP student in class 10th.

这时,该指针description指向这个字符串 “Zara ali a DSP student in class 10th.” 的首地址。

实际上, “Zara ali a DSP student in class 10th.”是一个字符串常量,它作为表达式代表的是一个指针常量,指向第一个字符。所以,将该指针常量赋值给一个指针是很合理的,并且该指针指向该字符串的第一个字符元素。

有关字符串常量的博文:字符串常量,非常精彩!

但是下面的这种情况是不允许的,就是对该指针进行strcpy操作:

E2:


  
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. int main()
  5. {
  6. char name[100];
  7. char *description;
  8. strcpy(name, "Zara Ali");
  9. strcpy(description, "Zara ali a DSP student in class 10th...");
  10. printf("Name = %s\n", name );
  11. printf("Description: %s\n", description );
  12. }

运行结果:


  
  1. $gcc -o main *.c
  2. $main
  3. timeout: the monitored command dumped core
  4. sh: line 1: 135176 Segmentation fault timeout 10s main

是什么原因呢?可以确定,是没有为description指向的地址开辟一块内存存放后面的字符串。

这条指针声明语句:

char *description;

只是声明了一个指向char类型的指针,并没有为其分配内存空间,它不像数组的声明一样,声明的同时直接开辟了规定的内存空间,例如:

char name[100];

这条语句在编译时,就分配了 100 * sizeof( char )个字节的内存。

下面的例子是使用动态内存分配的相关函数分配了内存之后的操作,畅通无阻:

E3:


  
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. int main()
  5. {
  6. char name[100];
  7. char *description;
  8. strcpy(name, "Zara Ali");
  9. /* 动态分配内存 */
  10. description = (char *)malloc( 200 * sizeof(char) );
  11. if( description == NULL )
  12. {
  13. fprintf(stderr, "Error - unable to allocate required memory\n");
  14. }
  15. else
  16. {
  17. strcpy( description, "Zara ali a DPS student in class 10th");
  18. }
  19. printf("Name = %s\n", name );
  20. printf("Description: %s\n", description );
  21. }

  
  1. 运行结果:
  2. $gcc -o main *.c
  3. $main
  4. Name = Zara Ali
  5. Description: Zara ali a DPS student in class 10th

我写博客用的是线上写代码,这样比较方便,不用还打开软件创建一个工程等等步骤,直接写代码之后运行,分析符不符合我的想法,随时修改,十分方便:Online C Compiler

同样,上面这个例子中,必须对description这个指向字符的指针进行动态内存分配才能对其进行strcpy(字符串复制操作)操作,它不像你声明了一个数组一样,声明一个数组,会对其分配一定的内存,例如:

char name[100];

这条语句在编译时,就分配了 100 * sizeof( char )个字节的内存。

所以之后就不必担心内存有无的问题了,唯一值得担心的问题就是这里的内存够不够用,如果你确信够用,可以这么声明。但是,如果您预先不知道需要存储的文本长度,例如您向存储有关一个主题的详细描述。在这里,我们需要定义一个指针,该指针指向未定义所需内存大小的字符,后续再根据需求来分配内存,上例就是这么个用法。

当动态分配内存时,您有完全控制权,可以传递任何大小的值。而那些预先定义了大小的数组,一旦定义则无法改变大小。

上面的程序也可以使用 calloc() 来编写,只需要把 malloc 替换为 calloc 即可,如下所示:

calloc(200, sizeof(char));
 

重新调整内存的大小,使用realloc函数。

为什么要调整内存大小,是为了应付那些当时分配的内存大小不够用的情况,例子上面的例子,给description指针指向的地址分配了30 * sizeof( char ) 个字节的空间,然后进行如下操作:

E4:


  
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. int main()
  5. {
  6. char name[100];
  7. char *description;
  8. strcpy(name, "Zara Ali");
  9. /* 动态分配内存 */
  10. description = (char *)malloc( 30 * sizeof(char) );
  11. if( description == NULL )
  12. {
  13. fprintf(stderr, "Error - unable to allocate required memory\n");
  14. }
  15. else
  16. {
  17. strcpy( description, "Zara ali a DPS student.");
  18. }
  19. strcat( description, "She is in class 10th");
  20. printf("Name = %s\n", name );
  21. printf("Description: %s\n", description );
  22. /* 使用 free() 函数释放内存 */
  23. free(description);
  24. }

运行结果:

出现错误,那是因为之前定义的内存不够用了,这个时候你应该增加内存之后,在进行字符串拼接(strcat)操作。

这里,我必须用电脑上安装的codeblock才会出现这种提示,如果用线上的编辑器,显示的结果是这样的:


  
  1. $gcc -o main *.c
  2. $main
  3. Name = Zara Ali
  4. Description: Zara ali a DPS student.She is in class 1

也看出来是没有显示完全,但是这个结果并不如意!可见,线上的编辑器我们简单的谢谢博客用用即可,毕竟没有主流的软件强大!

下面是一个修正后的例子:

E5:


  
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. int main()
  5. {
  6. char name[100];
  7. char *description;
  8. strcpy(name, "Zara Ali");
  9. /* 动态分配内存 */
  10. description = (char *)malloc( 30 * sizeof(char) );
  11. if( description == NULL )
  12. {
  13. fprintf(stderr, "Error - unable to allocate required memory\n");
  14. }
  15. else
  16. {
  17. strcpy( description, "Zara ali a DPS student.");
  18. }
  19. /* 假设您想要存储更大的描述信息 */
  20. description = realloc( description, 100 * sizeof(char) );
  21. if( description == NULL )
  22. {
  23. fprintf(stderr, "Error - unable to allocate required memory\n");
  24. }
  25. else
  26. {
  27. strcat( description, "She is in class 10th");
  28. }
  29. printf("Name = %s\n", name );
  30. printf("Description: %s\n", description );
  31. /* 使用 free() 函数释放内存 */
  32. free(description);
  33. }

  
  1. 运行结果:
  2. $gcc -o main *.c
  3. $main
  4. Name = Zara Ali
  5. Description: Zara ali a DPS student.She is in class 10th

最后补充一个malloc以及realloc使用的经典案例:


  
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main () {
  4. char *str;
  5. /* Initial memory allocation */
  6. str = (char *) malloc(15);
  7. strcpy(str, "tutorialspoint");
  8. printf("String = %s, Address = %u\n", str, str);
  9. /* Reallocating memory */
  10. str = (char *) realloc(str, 25);
  11. strcat(str, ".com");
  12. printf("String = %s, Address = %u\n", str, str);
  13. free(str);
  14. return(0);
  15. }

在Code:Blockz中运行结果为:

String = tutorialspoint,  Address = 2960224
String = tutorialspoint.com,  Address = 2952960

Process returned 0 (0x0)   execution time : 0.930 s
Press any key to continue.

初次见这个运行结果时候,前面的部分我还能接受,但仔细看了地址后,大吃一惊。(还是菜呀!哈哈哈),有些人可能会问,为什么地址不一样了,realloc不是在原内存的基础上添加了一块吗?所以最后返回的指针应该不变呀。这就是对realloc这个函数掌握的不够了。

我专门写一篇博文来记录这个问题吧,毕竟是自己踩过的坑!我相信也会有人会有此疑惑,但如果接着写的话,恐怕就不能够直接搜索到这个知识点了。

【 C 】关于学习 realloc 踩过的那些坑

给个别人的博文参考地址:http://www.cnblogs.com/hnrainll/archive/2011/07/27/2118812.html

最后推荐一篇博文,以后我也会仔细看看:

https://blog.csdn.net/sendfeng/article/details/6215016

 

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/82622485

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。