首页 > 编程语言 >C/C++中哪些数据存放于栈区、堆区、静态区、常量区的详细说明

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

时间:2024-09-18 20:21:01浏览次数:11  
标签:栈区 释放 常量 静态 堆区 char2 C++ 内存 分配

文章目录

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 字节。

标签:栈区,释放,常量,静态,堆区,char2,C++,内存,分配
From: https://blog.csdn.net/ZWW_zhangww/article/details/142342097

相关文章

  • c++primer第七章函数学习笔记
    函数的基本知识定义函数无返回值voidfunctionName(parameterList){  statement(s);  return;//optional}有返回值  typeNamefuntionName(parameterList)  {    statements;    returnvalue;  }#include<iostream>usi......
  • 南沙C++信奥老师解一本通题:1337:【例3-2】单词查找树
    ​【题目描述】在进行文法分析的时候,通常需要检测一个单词是否在我们的单词列表里。为了提高查找和定位的速度,通常都画出与单词列表所对应的单词查找树,其特点如下:1.根结点不包含字母,除根结点外每一个结点都仅包含一个大写英文字母;2.从根结点到某一结点,路径上经过的字母依次连起......
  • java.lang.UnsatisfiedLinkError: dlopen failed: library "libc++_shared.so" not fo
    一、概述在AndroidStudio中集成opencv,使用其native函数时报的一个错误 二、解决办法opencv提供的native文件夹中提供的是动态库但是在gradle中的配置中,配置的stl是静态的,将其改为shared就行了externalNativeBuild{cmake{cp......
  • C++ vector 列表初始化
    vector<int>vl(10);//v1有10个元素,每个的值都是0vector<int>v2{10};//v2有1个元素,该元素的值是10vector<int>v3(10,1);//v3有10个元素,每个的值都是1vector<int>v4{10,1};//v4有2个元素,值分别是10和1如果初始化时使用了花括号的形式但是提供的值又不能......
  • 【C++】多态的认识和理解
    个人主页文章目录⭐一、多态的概念......
  • C++浮点数半精度与单精度的相互转换
    代码//单精度转半精度unsignedshortcpu_float2half(floatf){unsignedshortret;unsignedx=*((int*)(void*)(&f));unsignedu=(x&0x7fffffff),remainder,shift,lsb,lsb_s1,lsb_m1;unsignedsign,exponent,mantissa;//Getrid......
  • C++14的一些新特性
    记录一些C++14的一些特性: 函数返回值类型推导:C++14对函数返回类型推导规则做了优化:#include<iostream>usingnamespacestd;autofunc(inti){returni;}intmain(){cout<<func(4)<<endl;return0;}返回值类型推导也可以用在模板中:#include......
  • Rust中的&运算符取一个变量的地址与C/C++中意义相同么?如果不同又有什么区别呢?
    Rust中的&运算符与C/C++中的&运算符有相似之处,但它们的行为和作用有一些关键区别,特别是在所有权、内存安全和编译期检查方面。1.相似之处在Rust和C/C++中,&运算符都用于获取变量的地址,即生成一个指针或引用。它们的作用可以概括为:将一个值的引用或地址作为结果,而不......
  • C++中一般指针,指针数组,数组指针
    凤凰台上凤凰游,凤去台空江自流。吴宫花草埋幽径,晋代衣冠成古丘。三山半落青天外,二水中分白鹭洲。总为浮云能蔽日,长安不见使人愁。                            ——《登金陵凤凰台》【唐】李白 今天是中秋节,小......
  • C++11的一些特性
    记录一下使用过的C++11的一些特性,大致分为三部分:并发相关,智能指针相关,chrono。 并发相关:std::thread相关:#include<iostream>#include<thread>usingnamespacestd;intmain(){autofunc=[](){for(inti=0;i<10;++i){cout<<i<......