变量内存分配

c语言内存分配之局部变量内存分配 局部变量内存分配情况: 局部变量保存在栈中(保存地址由高地址到低地址)。 先定义先分配内存。            由此可见局部变量分配空间的顺序和变量的声明顺序直接相关,同时按照内存地址由高到低的顺序进行空间分配. 先定义,先分配,地址由高到低 数组越界问题(看图3和图4)       由于首先声明的是数组a[4],于是在高位 阅读详情

预备知识—程序的内存分配 
一个由C/C++编译的程序占用的内存分为以下几个部分 
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 
2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。
3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放 
4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放 
5、程序代码区—存放函数体的二进制代码。

一个正常的程序在内存中通常分为程序段,数据端和堆栈三部分。程序段里放着程序的机器码和只读数据,这个段通常是只读,对它的写操作是非法的。数据段放的是程序中的静态数据。动态数据则通过堆栈来存放。在内存中,它们的位置如下: 
+------------------+ 内存低端 
| 程序段 | 
|------------------| 
| 数据段 | 
|------------------| 
| 堆栈 | 
+------------------+ 内存高端 
堆栈是内存中的一个连续的块。一个叫堆栈指针的寄存器(SP)指向堆栈的栈顶。堆栈的底部是一个固定地址。堆栈有一个特点就是,后进先出。也就是说,后放入的数据第一个取出。它支持两个操作,PUSH和POP。PUSH是将数据放到栈的顶端,POP是将栈顶的数据取出。
在高级语言中,程序函数调用和函数中的临时变量都用到堆栈。为什么呢?因为在调用一个函数时,我们需要对当前的操作进行保护,也为了函数执行后,程序可以正确的找到地方继续执行,所以参数的传递和返回值也用到了堆栈。通常对局部变量的引用是通过给出它们对SP的偏移量来实现的。另外还有一个基址指针(FP,在Intel芯片中是BP),许多编译器实际上是用它来引用本地变量和参数的。通常,参数的相对FP的偏移是正的,局部变量是负的。 
当程序中发生函数调用时,计算机做如下操作:首先把参数压入堆栈;然后保存指令寄存器(IP)中的内容,做为返回地址(RET);第三个放入堆栈的是基址寄存器(FP);然后把当前的栈指针(SP)拷贝到FP,做为新的基地址;最后为本地变量留出一定空间,把SP减去适当的数值。 

在函数体中定义的变量通常是在栈上,用malloc, calloc, realloc等分配内存的函数分配得到的就是在堆上。在所有函数体外定义的是全局量,加了static修饰符后不管在哪里都存放在全局区(静态区),在所有函数体外定义的static变量表示在该文件中有效,不能extern到别的文件用,在函数体内定义的static表示只在该函数体内有效。另外,函数中的"adgfdf"这样的字符串存放在常量区。

对比:
1 性能
栈:栈存在于RAM中。栈是动态的,它的存储速度是第二快的。stack
堆:堆位于RAM中,是一个通用的内存池。所有的对象都存储在堆中。heap

2 申请方式
stack: 由系统自动分配。 例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间 
heap: 需要程序员自己申请,并指明大小,在c中malloc函数 如p1 = (char *)malloc(10); 
在C++中用new运算符 如p2 = (char *)malloc(10); 但是注意p1、p2本身是在栈中的。

3 申请后系统的响应
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。 
堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时, 
会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

4 申请大小的限制
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。 
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

5 申请效率的比较
栈由系统自动分配,速度较快。但程序员是无法控制的。 
堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便. 
另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存,虽然用起来最不方便。但是速度快,也最灵活。

6 堆和栈中的存储内容
栈:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。 
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。 
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。

7 存取效率的比较
char s1[] = "aaaaaaaaaaaaaaa"; 
char *s2 = "bbbbbbbbbbbbbbbbb"; 
aaaaaaaaaaa是在运行时刻赋值的; 
而bbbbbbbbbbb是在编译时就确定的; 
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。 
比如: 
#include 
void main() 
{ 
char a = 1; 
char c[] = "1234567890"; 
char *p ="1234567890"; 
a = c[1]; 
a = p[1]; 
return; 
} 
对应的汇编代码 
10: a = c[1]; 
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh] 
0040106A 88 4D FC mov byte ptr [ebp-4],cl 
11: a = p[1]; 
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h] 
00401070 8A 42 01 mov al,byte ptr [edx+1] 
00401073 88 45 FC mov byte ptr [ebp-4],al 
第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了。 

小结: 
堆和栈的区别可以用如下的比喻来看出: 
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。 
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。

全局变量、静态数据、常量存放在全局数据区,所有函数的代码存放在代码区,为运行函数而分配的局部变量、函数参数、返回数据、返回地址等存放在栈区。   
所以在同一个进程里,多个任务(线程)的全局变量和静态变量都应该是共享同一块内存(全局数据区)   
而在不同的进程里,重新加载了代码,各个进程间的全局变量和静态变量当然不是拥有同一块内存。   
在psos下,各个任务是不同的线程,所以各个任务的全局变量和静态变量是在同一块内存。而我的另一个程序中(在sco unix),是每次运行都是一个新的进程,所以各个进程的全局变量和静态变量拥有不同的内存

内存分配和变量存储位置 在编程中,内存分配和变量存储位置是一个重要的概念。栈内存分配适用于自动分配和释放的局部变量,而堆内存分配适用于手动分配和释放的动态变量。变量的存储位置取决于其类型和声明方式,常见的存储位置包括栈、堆和静态存储区。了解内存分配和变量存储位置的概念对于编写高效、可靠的程序至关重要。正确地管理内存资源可以避免内存泄漏和未定义行为。请记住,在使用堆内存分配时,一定要及时释放不再使用的内存,以避免内存泄漏。希望本文能够帮助你理解内存分配和变量存储位置的概念,并在编程中正确地应用它们。 阅读详情

相关推荐

HackRF实战:用Portapack扩展板玩转GPS信号模拟(附固件刷写教程)

本文详细介绍了如何使用HackRF与Portapack扩展板进行GPS信号模拟,包括固件刷写、信号生成与发射配置等实战操作。通过专业工具和优化技巧,读者可以掌握软件无线电的高级应用,解决手机定位难题,同时强调安全合规使用的重要性。

weixin_28717431的博客 362

Arm汇编学习笔记(六)——函数调用栈空间以及fp寄存器

Arm上函数调用的规则在ARM System Developer's Guide文档中的ATPCS部分有详细的定义,这里主要通过函数调用过程中函数栈的情况来说明fp和sp等寄存器的作用。有关ATPCS的详细内容可以去文档中看。 fp叫做frame pointer寄存器,即栈帧指针寄存器;sp叫做stack pointer寄存器,即栈指针寄存器。那么它们具体的作用是什么呢? 首先,大家知

beyond702的专栏 2万+

Abaqus滞回问题求解—浆锚连接装配式剪力墙滞回模拟

当下土木工程研究生,多数都在从事装配式混凝土构件安全或装配式混凝土构件连接节点力学性能的研究。研究这类问题,几乎脱离不开对有限元软件的使用,Abaqus求解能力非常强大,但模型处理能力相对较弱。装配式混凝土结构的有限元计算与传统现浇结构相比,其节点处理起来相对复杂,计算结果往往需要凸显出连接节点力学特性,所以对建模精程度的要求较高。所以向大家介绍一款工具—HyperMesh软件(一下简称Hm),它是专业的有限元前处理工具,用于处理装配式混凝土构件或连接节点有限元模型比较合适。这篇文章主要介绍如何利用Hm处理

qq_31918049的博客 2901

JAVA变量及内存分配

JAVA变量的要素包括便变量名、类型、作用域。本质上讲,变量实际上是内存中的一块区域,使用变量名来访问这块区域。每个变量使用前必须要先声明,然后赋值才可以使用。根据变量的声明位置,可以分成①局部变量:声明在方法体内(包含方法的参数)或语句块内部的变量。②成员变量:声明在方法体外,类内部的变量。成员变量可以使用任何一种数据类型,包括引用类型和基本类型(见下面),在定义成员变量时可以对他进行初始化,如果

致命的数据 1719

机械臂的运动学分析-工业机器人

机械臂的运动学是研究机械臂各连杆坐标系之间的运动关系,是对机械臂进行运动控制的基础。本章分析了所设计的六自由度机械臂的运动学。理论上六自由度机械臂的工作空间是一个近似球形区域,能够覆盖机械臂所在的位置,但由于机械臂关节的运动范围受到限制,机械臂末端会存在一些不能到达的工作死区,使得机械臂的工作范围和灵活性受到限制。理论上六自由度机械臂的工作空间是一个近似球形区域,能够覆盖机械臂所在的位置,但由于机械臂关节的运动范围受到限制,机械臂末端会存在一些不能到达的工作死区,使得机械臂的工作范围和灵活性受到限制。

qq_59137727的博客 6648

使用podman 容器化安装DIFY

本文阐述了使用podman容器化安装DIFY的过程

wengad的博客 1901

变量内存分配知多少

  繁忙的工作总容易让我们忽视最基础的知识,手里的活停一停,下楼呼吸下新鲜空气(北京的朋友抱歉了),让大脑切换下进程。   回想工作中我们所遇到的难点,嗯,好多都是我们对基础知识了解得不够透彻,或者说只知道了表层的东西。而往往我们总是被这些表层东西所欺骗了,最后等待我们的就是bug量增多,性能低下,运行不稳定,维护成本剧增,客户满意度下降,更严重的便可能导致项目进入恶性循环。可想而知,...

dhvyl82208的专栏 208

Codex智能体从零搭建:环境配置、代码管理与MCP扩展实战

AI智能体(Agent)作为连接大语言模型与实际应用的关键技术,通过感知、决策与执行框架,将AI能力融入具体工作流。其核心原理在于利用提示工程、上下文管理与工具调用,将自然语言指令转化为可执行操作。在软件开发领域,AI智能体能够显著提升代码生成、项目管理和自动化任务的效率。通过Model Context Protocol(MCP)等标准化协议,智能体可以安全、结构化地集成外部工具与服务,实现能力扩展。本文聚焦于Codex这一AI驱动的代码助手平台,详细解析其环境配置、代码索引、记忆系统等核心模块,并深入探讨

weixin_34220179的博客 589

C和C++中const变量内存分配问题详解

一、const变量的内存分配 1.const全局变量,或者static,extern 关键字 此时该常量是存放在.rodata段的—Read Only Data也就是常量区,是无法通过取地址方式去修改的,修改内容会报段错误(gcc++编译器:Segmentation fault(core dumped))。   例如extern const int i=10,   static const int i=10。 2.const局部变量 在C语言中,const局部变量在栈分配内存,不能通过赋值,自

u014157109的博客 8014

SolidWorks速成教程P1——简介及基础操作

SolidWorks教程P1——简介及基础操作

嵌入式阿齐Archie 2万+

【NI Multisim 14.0原理图设计基础——元器件分类】

电阻(RESISTOR):该元器件栏中的电阻都是标称电阻,是根据真实电阻元器件而设计的,其电阻值不能改变。 排阻(RESISTOR PACK):相当于多个电阻并列封装在一个壳内,它们具有相同的阻值。 电位器(POTENTIOMETER):即可调电阻,可以通过键盘字母动态调节电阻,大写表示增加电阻值,小写表示减小电阻值,调节增量可以设置。 电容(CAPACITOR):所有电容都是无极性的,不能改变参数,没有考虑误差,也未考虑耐压大小。 电解电容器(CAP_ELECTROLIT):所有电容都是有极性的,“+”极

RL2698853114的博客 4万+

java变量内存分配_java变量在内存分配原理

程序变量如何在内存分配的?其值又存放在哪里?下面以java为语言基础讲解一、基本原理例:int a = 10;boolean b = false;上面例子有两行语句,分别定义了变量a(int型,在32位系统中是4位字节),b(布尔型,只占1个字节)。都是基本类型,占位长度确定,内存分配如下:内存地址值0x01100x020x030x040x05false上面表格代表内存分布图,每一行代表1个字节,...

weixin_42504649的博客 618

MIPI CSI-2

来源:公众号瓜大三哥版权归三哥所有1 MIPI简介2 MIPI CSI-2简介2.1 MIPI CSI-2 的层次结构2.2 CSI-2协议层2.3 打包/解包层2.4 ...

OpenFPGA的博客 2113

实例变量和类变量内存分配

Java向程序员许下一个承诺:无需关心内存回收,java提供了优秀的垃圾回收机制来回收已经分配的内存。大部分开发者肆无忌惮的挥霍着java程序的内存分配,从而造成java程序的运行效率低下! java内存管理分为两方面:     1,内存的分配:指创建java对象时,jvm为该对象在堆内存中所分配的内存空间。 2,内存的回收:指当该java对象失去引用,变成垃圾时,jvm的垃圾回收机制自动清

Cheers_FOR_Crazy 3429

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

pytorch中的变量内存分配

请你分析一下这段pytorch代码其中的变量内存分配情况以及各变量之间的关系?(让Deepseek R1 671b来答,AI-4o这种问题回答不好)

qq_73361455的博客 469

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

结构体变量内存分配问题

由于系统 遵守两个原则 1.为结构体变量的成员变量分配内存的起始地址必须为成员变量内存长度的整数倍。 2.结构体变量内存的总大小必须为sizeof(结构体成员变量)(最大的)的整数倍。 struct Demo{ char a;//sizeof(char)=1 int b;//sizeof(int)=4 flloat c;//sizeof(float)=4 double d;//sizeof...

123向前走的博客 4675

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

const类型变量的内存分配

<br />如果是局部自动变量 加了 const 只是起了个标记的作用,变量还是分配在栈区 <br />如果是全局变量,就会分配在只读数据段,也就是常量区 <br />程序验证如下: <br />  <br />#include  <iostream> <br />using namespace std; <br /><br />const int g_c = 0;          //如果是global变量的话确实是分配在常量区  <br />int g_a; <br />int main() <br

yyhtsm的专栏 1842

变量的内存分配

当在程序中声明一个变量时,编译器会给变量预留内存空间。这种预留内存空间的过程就叫分配。全局变量在程序开始执行时分配,直到程序执行完之后才会释放内存空间。局部变量只有但函数调用时才会分配内存空间。变量本身在分配给这个函数的存储空间中分配,函数的存储空间叫函数的帧(frame)。只要函数在运行,局部变量在帧中的地址始终是不变的。当函数返回时,帧以及它的所有变量都被丢弃,以便让别的函数使...

qq_38475134的博客 1984

JAVA定义变量内存分配_Java变量的声明、内存分配及初始化

class Person{String name;int age;void talk(){System.out.println("我是: "+name+", 今年: "+age+"岁");}}public class TestJava2_1{public static void main(String args[]){Person p;if (p == null){p = new Person(...

weixin_31002061的博客 574

Java变量的声明、内存分配及初始化

class Person { String name; int age; void talk() { System.out.println("我是: "+name+", 今年: "+age+"岁"); } } public class TestJava2_1 { public static v...

aaronyyl1027的博客 384

变量的内存分配和释放

一般地,无论是全局变量还是局部变量,如果它是非指针类型的,则声明后被自动分配内存。如果是全局变量,还会被初始化为0:数值类型的为0,布尔类型的为False,字符的为‘’;如果是局部变量,则不会被初始化,因此,它的值是不确定的(取决于别的程序对这块内存的操作)。对于非Variant和File类型的全局变量,还可以在声明是指定初始值(如:var I: integer = 7),但是对任何的局部变量都不...

weixin_34150503的博客 127

C语言中变量的内存分配以及内存分配的类型详解

局部变量所占的内存空间是在运行过程中分配到栈区的。

qq_59938293的博客 2123

关于全局变量内存分配的顺序

全局变量内存分配的顺序我们知道C语言中,局部变量分配顺序是固定的,可是你有没有想过全局变量分配的顺序呢?没有,那么首先用2种方式运行下面的程序:#include #define ONE 1 // 0#if ONEint a, b;#elseint b, a;#endif // ONEvoid main(){#if ONEcout cout  #elsecout cout  #endif // ON

峰子的专栏 4091

Java中变量的内存分配

Java内存管理分为两个方面:内存分配 内存回收 这里的内存分配特指当创建一个java对象时JVM为该对象在堆内存中分配内存空间。 内存回收:当java对象失去引用,变成垃圾时,           JVM的垃圾回收机制会(1)自动清理该对象(2)回收该对象所占用的内存。 虽然JVM内置了垃圾回收机制,但是java程序依然会存在内存泄漏,如果肆无忌惮创建对象,让系统分配内存,最后由垃圾回收

沙漏 2108

变量的内存分配:内存对齐

数据结构还有变量等等都需要占有内存,在很多系统中,它都要求内存分配的时候要对齐,这样做的好处就是可以提高访问内存的速度。#include  2 using namespace std; 3  4 struct X1 5 { 6   int i;//4个字节 7   char c1;//1个字节 8   char c2;//1个字节 9 };10 11 struct X212 {13   char c1;//1个字节14   int i;//4个字节15   char c2;//1个字节16 };17 18 

ToSoftWare的专栏 3979
上一篇: linux输入子系统
下一篇: USB枚举过程
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值