前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C/C++中哪些数据存放于栈区、堆区、静态区、常量区的详细说明

C/C++中哪些数据存放于栈区、堆区、静态区、常量区的详细说明

作者头像
用户11286421
发布2024-09-23 20:14:50
990
发布2024-09-23 20:14:50
举报
文章被收录于专栏:学习

1. 栈区(Stack)

栈区用于存放局部变量和函数调用信息,它的内存由编译器自动分配和释放,具有自动管理的特点。栈区的内存分配遵循先进后出的原则,生命周期是非常短暂的。

存储内容:

局部变量(例如函数中的局部变量、参数) 函数的返回地址、调用信息 临时对象(比如函数返回值、临时创建的变量

特点: 自动管理:栈上的变量在函数结束时自动释放,不需要显式的内存管理。 高效:栈的分配和释放效率很高,通常通过直接的指针调整完成。 生命周期短:栈上变量的生命周期限于作用域,出了作用域即被释放。

2. 堆区(Heap)

堆区用于存放程序运行时动态分配的内存,程序员需要手动管理(分配和释放)。C++中可以通过new分配堆内存,通过delete释放。

存储内容: 动态分配的内存,如通过new分配的对象或数组。

特点: 手动管理:需要显式使用new分配内存,delete释放内存,防止内存泄漏。 灵活性:堆上的内存可以在程序运行时根据需求动态分配,存储的数据不受作用域限制,可以在多个函数之间共享。

3. 静态区(Static)

静态区用于存放全局变量、静态变量(static关键字修饰的变量)和静态成员变量。这些变量在程序开始时分配内存,并在程序结束时释放,具有全局的生命周期。

存储内容: 全局变量:即作用域为整个程序的变量。 静态变量:局部静态变量在第一次进入所在函数时初始化,并且在后续调用中保留其值。 静态成员变量:类的static成员,属于类而非实例对象。

特点: 全局生命周期:静态区中的变量在程序运行期间始终存在,直到程序结束才被释放。 一次性初始化:静态变量在程序运行时或第一次使用时初始化,且仅初始化一次。

4. 常量区(Read-Only or Constant Section)

常量区用于存放程序中不可修改的常量数据。这个区域通常是只读的,防止程序试图修改这些常量,任何修改尝试都会导致程序异常(如段错误)。

存储内容: 字符串常量:例如const char* str = “hello”;中的"hello"字符串存放在常量区。 const修饰的全局变量:如const int a = 10;(注意:const修饰的局部变量在栈区)。 编译器决定存储的常量数据:编译器可能将某些不变的常量数据(如浮点数、整型常量等)放在常量区。

特点: 只读:程序无法修改常量区的内容,通常对这些区域的写操作会导致运行时错误。 共享性:常量区的数据可以被多个函数或模块共享,不重复存储。

总结:

下面是自己画的简易图:

栈区以及堆区旁边蓝色的箭头表示两者的生长方向 栈:从内存的顶部(高地址)开始,逐渐向下(低地址)分配内存。 堆:从内存的底部(低地址)开始,逐渐向上(高地址)分配内存。

栈(Stack)的生长:

生长方向:栈一般是向下生长的,即从高地址向低地址增长。这种分配是由编译器自动管理的,栈主要用于存储局部变量、函数调用帧(包括函数参数、返回地址等)。 分配与释放:栈上的内存分配和释放是自动的,随着函数的调用与返回,内存会自动进行分配和回收。比如,当进入一个函数时,该函数的局部变量会被分配到栈上;当函数执行结束时,栈上的内存会自动释放,不需要手动管理。 特点: 内存分配效率高,因为是连续的。 容量有限,一般有固定的大小,如果超过栈的容量,就会导致栈溢出(Stack Overflow)。

堆(Heap)的生长:

生长方向:堆的生长方向通常是向上生长的,即从低地址向高地址增长。堆内存是通过动态内存分配函数(如 malloc、free,或者在C++中使用 new、delete)进行管理的。 分配与释放:堆上的内存需要手动管理,程序员必须显式地进行分配和释放。如果没有及时释放内存,可能会导致内存泄漏(memory leak)。另外,如果反复分配和释放内存,还可能产生内存碎片,降低内存使用效率。

特点: 堆的大小仅受系统可用内存的限制,理论上可以动态扩大。 动态分配的内存灵活性强,但内存分配速度比栈慢。 需要小心管理,否则容易出现内存管理错误,比如忘记释放内存导致内存泄漏。

测试

下面分享一道例题,方便读者自己进行测试

一答案

globalVar在哪里? 选项:C. 数据段(静态区) 全局变量(globalVar)是在数据段(静态区)分配内存的。

staticGlobalVar在哪里? 选项:C. 数据段(静态区) 静态全局变量(staticGlobalVar)也是在数据段(静态区)分配内存。

staticVar在哪里? 选项:C. 数据段(静态区) 静态局部变量(staticVar)在数据段(静态区)分配内存,并且生命周期贯穿整个程序执行。

localVar在哪里? 选项:A. 栈 局部变量(localVar)是在栈上分配的,它的生命周期仅限于函数调用期间。

num1在哪里? 选项:A. 栈 局部数组(num1)也是在栈上分配的。

char2在哪里? 选项:A. 栈 字符数组(char2)是在栈上分配的。

*char2在哪里? 选项:A. 栈 char2 是字符数组的名称,它在栈上分配,因此它的内容也在栈上。

pChar3在哪里? 选项:A. 栈 指针 pChar3 是局部变量,在栈上分配。

*pChar3在哪里? 选项:D. 代码段(常量区) pChar3 指向的是一个字符串常量 “abcd”,而字符串常量存储在代码段(常量区)。

ptr1在哪里? 选项:A. 栈 指针 ptr1 是局部变量,存储在栈上。

*ptr1在哪里? 选项:B. 堆 ptr1 指向的是通过 malloc 动态分配的内存,存储在堆上。

二答案

sizeof(num1) = 40 num1 是一个包含 10 个 int 元素的数组。在大多数系统中,int 占用 4 字节,因此数组占用 40 字节(4 * 10 = 40)。

sizeof(char2) = 5 char2 是一个字符数组,包含 “abcd” 和终止字符 \0。因此,sizeof(char2) 返回 5。

strlen(char2) = 4 strlen(char2) 计算的是字符串 “abcd” 的长度,不包括终止字符 \0,所以返回 4。

sizeof(pChar3) = 8(在 64 位系统上) pChar3 是一个指针,在 64 位系统上,指针的大小是 8 字节。如果是 32 位系统,则为 4 字节。

strlen(pChar3) = 4 pChar3 指向字符串常量 “abcd”,strlen(pChar3) 返回 4。

sizeof(ptr1) = 8(在 64 位系统上) ptr1 是一个指针,大小为 8 字节(在 64 位系统上)。如果是 32 位系统,则为 4 字节。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-09-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 栈区(Stack)
  • 2. 堆区(Heap)
  • 3. 静态区(Static)
  • 4. 常量区(Read-Only or Constant Section)
  • 总结:
  • 栈(Stack)的生长:
  • 堆(Heap)的生长:
  • 测试
    • 一答案
      • 二答案
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档