C语言指针理解 --- 代码配合图形讲解内存四区

简介: C语言指针理解 --- 代码配合图形讲解内存四区
1. #define _CRT_SECURE_NO_DEPRECATE
2. 
3. #include "stdlib.h"
4. #include "string.h"
5. #include "stdio.h"
6. 
7. 
8. //c++编译器优化
9. char *getStr1()
10. {
11.   char *p = "abcd1";    //这里定义的abcd1放在全局区
12.   return p;
13. }
14. 
15. char *getStr2()
16. {
17.   char *p = "abcd1";    //这里定义的abcd1也放在全局区,因为上面已经定义了abcd1,所以这里的abcd1不再重新分配内存
18.   return p;
19. }
20. 
21. char *getStr3()
22. {
23.   char buf[100];
24.   memset(buf, 0, sizeof(buf));
25.   strcpy(buf, "abcd1");
26.   return buf;
27. }
28. 
29. 
30. //在被调用函数里面malloc的内存,首地址传给调用函数有两种方法:
31. /*
32. 1、return      :下面的getStr就是实例
33. 2、指针做函数参数
34. */
35. char *getStr4()
36. {
37.   char *p = NULL; //p是分配在栈区的,但是p指向的内存空间的变量是分配在堆区的
38.   p = (char *)malloc(100);//在堆上分配100字节的空间
39. 
40.   strcpy(p, "abcdefg");   //这句话的理解
41.   //先在全局区的常量区分配一块内存,放置abcdefg,
42.   //然后将abcdefg拷贝到上一步堆上分配的空间中
43. 
44.   return p;
45. }
46. 
47. 
48. void main(void)
49. {
50.   int a = 0;
51.   char *p1 = NULL;
52.   char *p2 = NULL;
53.   char *p3 = NULL;
54.   p3 = (char *)malloc(100);
55.   p1 = getStr1();
56.   p2 = getStr2();
57. 
58.   printf("getStr2():%s....\n", getStr2());
59. 
60.   //这里调用getStr3输出的是乱码,是因为buf是分配在栈区的,
61.   //调用getStr3结束之后buf分配的空间就会被销毁,所以无法返回
62.   printf("getStr3():%s\n", getStr3());  
63. 
64.   //这里调用getStr4之后,是可以正确的返回的,
65.   printf("getStr4():%s\n", getStr4());
66. 
67.   printf("p1:%d....\n", p1);
68.   printf("p2:%d....\n", p2);
69.   system("pause");
70. }
71.

 

getStr4内存模型图

 

总结:

1. 内存四区分别为:代码区、全局区、堆区、栈区

  • 代码区的特点:共享和只读
  • 存放在全局区的有:全局变量、静态变量(包括全局静态变量和局部静态变量)、常量(字符串常量和const修饰的全局变量,const修饰的局部变量放在栈区)
  1.    全局区再细分一点分为bss段和data段,bss段存放的是未初始化的全局变量和未初始化的静态变量,已经初始化的全局变量和已经初始化的静态变量存放在data段。
  • 栈区:存放临时变量(包括语句块内的变量、函数参数等),由编译器管理开辟和释放
  • 堆区:malloc的变量,由程序员管理开辟和释放

2. 结合上面的code和画图示意的看,彻底搞懂内存四区模型。

相关文章
|
安全 Java 应用服务中间件
Spring Boot + Java 21:内存减少 60%,启动速度提高 30% — 零代码
通过调整三个JVM和Spring Boot配置开关,无需重写代码即可显著优化Java应用性能:内存减少60%,启动速度提升30%。适用于所有在JVM上运行API的生产团队,低成本实现高效能。
1417 3
|
安全 Java 容器
告别空指针噩梦:Optional让Java代码更优雅
告别空指针噩梦:Optional让Java代码更优雅
611 94
|
存储 大数据 Unix
Python生成器 vs 迭代器:从内存到代码的深度解析
在Python中,处理大数据或无限序列时,迭代器与生成器可避免内存溢出。迭代器通过`__iter__`和`__next__`手动实现,控制灵活;生成器用`yield`自动实现,代码简洁、内存高效。生成器适合大文件读取、惰性计算等场景,是性能优化的关键工具。
585 2
|
安全 C语言 C++
比较C++的内存分配与管理方式new/delete与C语言中的malloc/realloc/calloc/free。
在实用性方面,C++的内存管理方式提供了面向对象的特性,它是处理构造和析构、需要类型安全和异常处理的首选方案。而C语言的内存管理函数适用于简单的内存分配,例如分配原始内存块或复杂性较低的数据结构,没有构造和析构的要求。当从C迁移到C++,或在C++中使用C代码时,了解两种内存管理方式的差异非常重要。
544 26
|
安全 C语言
C语言中的字符、字符串及内存操作函数详细讲解
通过这些函数的正确使用,可以有效管理字符串和内存操作,它们是C语言编程中不可或缺的工具。
665 15
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
688 7
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
存储 编译器 程序员
【C语言】内存布局大揭秘 ! -《堆、栈和你从未听说过的内存角落》
在C语言中,内存布局是程序运行时非常重要的概念。内存布局直接影响程序的性能、稳定性和安全性。理解C程序的内存布局,有助于编写更高效和可靠的代码。本文将详细介绍C程序的内存布局,包括代码段、数据段、堆、栈等部分,并提供相关的示例和应用。
1045 5
【C语言】内存布局大揭秘 ! -《堆、栈和你从未听说过的内存角落》
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
2041 9
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
748 7
|
存储 缓存 算法
【C语言】内存管理函数详细讲解
在C语言编程中,内存管理是至关重要的。动态内存分配函数允许程序在运行时请求和释放内存,这对于处理不确定大小的数据结构至关重要。以下是C语言内存管理函数的详细讲解,包括每个函数的功能、标准格式、示例代码、代码解释及其输出。
781 6