变量存储地址

合集下载

C语言变量存储类别和内存四区

C语言变量存储类别和内存四区

C语言变量存储类别和内存四区C语言变量存储类别和内存四区C语言是一门通用计算机编程语言,应用广泛。

C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

下面我们一起来看看C语言变量存储类别和内存四区的介绍,欢迎大家阅读!C语言变量存储类别和内存四区变量存储类别变量声明/定义的一般形式:存储类别数据类型变量名存储类别指的是数据在内存中存储的方法。

存储方法分为静态存储和动态存储两大类。

标准C语言为变量、常量和函数定义了4种存储类型:extern、auto、static、register。

根据变量的存储类别,可以知道变量的作用域和存储期。

这4种存储类型可分为两种生存期限:永久的(在整个程序执行期都存在)和临时的(暂时保存在堆栈和寄存器中)。

extern和static用来标识永久生存期限的“变量和函数”,而anto和register用来标识临时生存期限的"变量"。

只有变量才有临时生存期限。

一个变量和函数只能具有一个存储类型,也只能有一种生存期限。

内存中供用户使用的空间有三部分:程序区:存放程序的可执行代码;静态存储区:存放静态变量(全局变量和静态局部变量);动态存储区:存放函数调用时调用函数的现场保护和返回地址、函数形参、自动局部变量;变量的声明分为”定义性声明“(需建立存储空间,如:int a;)和”引用性声明“(不需建立存储空间,如extern a;)。

广义上讲,声明包括定义,一般为叙述方便,把建立存储空间的声明称定义,而不不需建立存储空间的声明称声明。

auto函数中的局部变量,如果不用关键字static加以声明,编译系统对它们是动态地分配存储空间的。

函数的形参和在函数中定义的变量(包括在复合语句中定义的变量)都属此类。

在调用该函数时,系统给形参和函数中定义的变量分配存储空间,数据存储在动态存储区中。

在函数调用结束时就自动释放这些空间。

51单片机程序和变量存储位置

51单片机程序和变量存储位置

51单⽚机程序和变量存储位置
⼀、概念理清
使⽤环境: keil2,⽣成的代码⼤⼩如下,data保存于内部RAM中,xdata保存于外部扩展SRAM中,code保存于FLASH中。

51单⽚机涉及的存储介质:
RAM: 内部RAM,每种51单⽚机都应该有,共256字节。

⼤⼩固定
SRAM:内存,掉电消失,外部扩展RAM,⽐内部RAM稍慢,作⽤⼀样,⽤于定义变量。

⼤⼩要查单⽚机具体⼿册。

最⼤0xFFFF FLASH:(保存程序代码,只能按扇区更改)。

⼤⼩要查单⽚机具体⼿册。

EEPROM:(保存掉电保存的数据,flash中也可以保存掉电保存的数据,但EEPROM可以按字节寻址,⽐FLASH稍微灵活⼀点)。

⼤⼩要查单⽚机具体⼿册。

.
⼆、C51存储修饰关键字:data、 idata 、pdata 、xdata、 code
char i : 使⽤的RAM前128字节。

⽆修饰,等同与data char i,对应keil2编译后的data
idata char i : 使⽤的RAM前256字节。

即包含了data,对应keil2编译后的data
pdata char i :使⽤SRAM的前256字节,对应keil2编译后的 xdata
xdata char i:使⽤SRAM的所有字节。

即包含了pdata,对应keil2编译后的 xdata
code char i: 使⽤FLASH中的空间,不可更改,相当于存储常量。

,对应keil2编译后的flash
三、EEPROM不是⽤于变量定义,⽤来保存掉电数据。

作⽤和FLASH⼀样。

STM32内存分配解析及变量的存储位置

STM32内存分配解析及变量的存储位置

STM32内存分配解析及变量的存储位置原⽂内存映射在⼀些桌⾯程序中,整个内存映射是通过虚拟内存来进⾏管理的,使⽤⼀种称为内存管理单元(MMU)的硬件结构来将程序的内存映射到物理RAM。

在对于 RAM 紧缺的嵌⼊式系统中,是缺少 MMU 内存管理单元的。

因此在⼀些嵌⼊式系统中,⽐如常⽤的 STM32 来讲,内存映射被划分为闪存段(也被称为Flash,⽤于存储代码和只读数据)和RAM段,⽤于存储读写数据。

STM32 的 Flash 和 RAM 地址范围笔者标题所说的内存是指 STM32 的 Flash 和 RAM,下图是 ARM Cortex M3 的地址映射图:从图中我们可以看到 RAM 地址是从 0x2000 0000 开始的,Flash地址是从 0x0800 0000 开始的,笔者将在下⽂中着重对这两部分进⾏剖析。

Flash代码和数据是存放在 flash 中的,下⾯是将 flash 内部进⾏细分之后的⼀张图,图中标明了代码段,数据段以及常量在 flash 中的位置。

如上图所⽰,Flash ⼜可以细分为这么⼏个部分,分别是⽂本段 (Text),其中⽂本段中⼜包含可执⾏代码 (Executable Code)和常量 (Literal Value),在⽂本段之后就是只读数据区域 (Read Only Data),当然并不是所有架构的单⽚机都满⾜这样⼀个排布规律,这⾥只针对ARM Cortex M3 系列,只读数据段后⾯接着的就是数据复制段 (Copy of Data Section),第⼀次遇到这个概念的朋友看到数据复制可能会有所疑惑,其实这个段充当的作⽤是存放程序中初始化为⾮ 0 值的全局变量的初始值,之所以要将初始值存放到这⾥,是因为全局变量是存放在 RAM 上的,RAM 上的值掉电便丢失,每次上电后这些变量是要进⾏重新赋值的,⽽重新赋的值就存放在这⾥。

那为什么不存放初始化为 0 的全局变量初始值呢,原因也很简单,既然是初始化为 0,那么在上电后统⼀对存放初始化为 0 的全局变量的那块区域清0就好了。

c语言指针类面试题

c语言指针类面试题

c语言指针类面试题C语言指针是面试中常见的话题之一,下面我将从多个角度回答与C语言指针相关的面试题。

1. 什么是指针?指针是一个变量,用于存储内存地址。

它可以指向其他变量或数据,通过指针可以直接访问或修改这些数据。

2. 指针和变量的区别是什么?变量是一个具体的数据存储单元,而指针是存储变量地址的变量。

变量有自己的值,而指针存储的是另一个变量的地址。

3. 如何声明和定义指针?在C语言中,可以使用以下语法声明和定义指针:c.数据类型指针变量名;例如:c.int ptr;这声明了一个指向整型数据的指针变量ptr。

4. 如何使用指针访问变量的值?可以使用解引用运算符()来访问指针所指向的变量的值。

例如,如果有一个整型指针ptr,可以使用`ptr`来获取ptr所指向的整型变量的值。

5. 指针与数组的关系是什么?数组名本身就是一个指针,它存储了数组的首地址。

可以通过指针算术运算来访问数组中的元素,例如`(array + i)`可以访问数组中的第i个元素。

6. 什么是指针的运算?指针的运算包括指针的加法、减法、比较等操作。

指针加法可以用于在指针上进行偏移,指针减法可以计算两个指针之间的距离,指针比较可以判断两个指针是否相等或者大小关系。

7. 什么是空指针和野指针?空指针是指未指向任何有效地址的指针,可以用NULL来表示。

野指针是指指向未知或无效地址的指针,使用野指针可能导致程序崩溃或产生不可预测的结果。

8. 如何避免野指针?避免野指针的方法包括及时初始化指针、在指针使用完毕后将其置为NULL、避免对未分配内存的指针进行解引用操作等。

9. 什么是指针的指针?指针的指针是指一个指针变量存储了另一个指针变量的地址。

通过指针的指针可以实现对指针的间接访问和修改。

10. 什么是指针数组和数组指针?指针数组是指一个数组中的元素都是指针类型。

数组指针是指一个指针,它指向一个数组的首地址。

以上是对C语言指针类面试题的回答,希望能对你有所帮助。

java中变量的存储位置

java中变量的存储位置

java中变量的存储位置1.寄存器:最快的存储区, 由编译器根据需求进⾏分配,我们在程序中⽆法控制.2. 栈:存放基本类型的变量数据和对象的引⽤,但对象本⾝不存放在栈中,⽽是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。

)3. 堆:存放所有new出来的对象。

4. 静态域:存放静态成员(static定义的)5. 常量池:存放字符串常量和基本类型常量(public static final)。

6. ⾮RAM存储:硬盘等永久存储空间这⾥我们主要关⼼栈,堆和常量池,对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。

栈中的数据⼤⼩和⽣命周期是可以确定的,当没有引⽤指向数据时,这个数据就会消失。

堆中的对象的由垃圾回收器负责回收,因此⼤⼩和⽣命周期不需要确定,具有很⼤的灵活性。

对于字符串:其对象的引⽤都是存储在栈中的,如果是编译期已经创建好(直接⽤双引号定义的)的就存储在常量池中,如果是运⾏期(new出来的)才能确定的就存储在堆中。

对于equals相等的字符串,在常量池中永远只有⼀份,在堆中有多份。

如以下代码:String s1 = "china";String s2 = "china";String s3 = "china";String ss1 = new String("china");String ss2 = new String("china");String ss3 = new String("china");对于通过new产⽣⼀个字符串(假设为”china”)时,会先去常量池中查找是否已经有了”china”对象,如果没有则在常量池中创建⼀个此字符串对象,然后堆中再创建⼀个常量池中此”china”对象的拷贝对象。

这也就是有道⾯试题:String s = new String(“xyz”);产⽣⼏个对象?⼀个或两个,如果常量池中原来没有”xyz”,就是两个。

(整理)第04章 变量的存储类型

(整理)第04章 变量的存储类型

第4章变量的存储类型4.1 概述C语言中的变量具有两种属性:根据变量所持有数据的性质不同而分为各种数据类型;根据变量的存储方式不同而分为各种存储类型.变量的数据类型决定了该变量所占内存单元的大小及形式;变量的存储类型规定了该变量所在的存储区域,因而规定了该变量作用时间的长短,即寿命的长短,这种性质又称为"存在性".变量在程序中说明的位置决定了该变量的作用域,即在什么范围内可以引用该变量,"可引用"又称为"可见",所以这种性质又称为"可见性".计算机的内存和CPU中的寄存器都可以存放数据,变量究竟存放在何处则由存储类来决定.存储类型用来说明变量的作用域,生存期,可见性和存储方式.下面解释几个概念:1 作用域:是该变量在其上有定义的程序部分,通俗的说,即该变量起作用的某个程序区域。

2 变量的生存期:是指它从产生到消亡的存在时间,即变量从定义开始到它所占有的存储空间被系统收回为止的这段时间。

3 变量的可见性的含义:在某个程序区域,可以对变量进行访问(或称存取)操作,我们则称该变量在该区域为可见的,否则为不可见的。

再引入几个概念:4 全局变量和局部变量在一个函数内部或复合语句内部定义的变量叫内部变量,又称为"局部变量"。

在函数外定义的变量称为外部变量,又称为"全局变量"。

如:int x ;void main( ){int a, b;float c;……..}x 定义在函数外,是全局int 型变量a,b定义在main()函数内是局部int 型变量c 定义在main()函数内是局部float 型变量6 动态存储变量和静态存储变量。

在程序运行期间,所有的变量均需占有内存,有的是临时占用内存,有的是整个程序运行过程中从头到尾占用内存。

对于在程序运行期间根据需要进行临时性动态分配存储空间的变量称为"动态存储变量",对于在程序运行期间永久性占用内存的变量称为"静态存储变量".一个正在运行的程序可将其使用内存的情况分为如下三类(如下图):程序代码区: 程序的指令代码存放在程序代码区。

data,bdata,idata,pdata,xdata,code存储类型与存储区

data,bdata,idata,pdata,xdata,code存储类型与存储区

data,bdata,idata,pdata,xdata,code存储类型与存储区data,bdata,idata,pdata,xdata,code存储类型与存储区bit是在内部数据存储空间中 20H .. 2FH 区域中⼀个位的地址,或者 8051 位可寻址 SFR 的⼀个位地址。

code是在 0000H .. 0FFFFH 之间的⼀个代码地址。

data是在 0 到 127 之间的⼀个数据存储器地址,或者在 128 .. 255 范围内的⼀个特殊功能寄存器(SFR)地址。

idata是 0 to 255 范围内的⼀个 idata 存储器地址。

xdata 是 0 to 65535 范围内的⼀个 xdata 存储器地址。

指针类型和存储区的关系详解⼀、存储类型与存储区关系data ---> 可寻址⽚内rambdata ---> 可位寻址的⽚内ramidata ---> 可寻址⽚内ram,允许访问全部内部rampdata ---> 分页寻址⽚外ram (MOVX @R0) (256 BYTE/页)xdata ---> 可寻址⽚外ram (64k 地址范围)code ---> 程序存储区 (64k 地址范围),对应MOVC @DPTR⼆、指针类型和存储区的关系对变量进⾏声明时可以指定变量的存储类型如:uchar data x和data uchar x相等价都是在内ram区分配⼀个字节的变量。

同样对于指针变量的声明,因涉及到指针变量本⾝的存储位置和指针所指向的存储区位置不同⽽进⾏相应的存储区类型关键字的使⽤如:uchar xdata * data pstr是指在内ram区分配⼀个指针变量("*"号后的data关键字的作⽤),⽽且这个指针本⾝指向xdata区("*"前xdata关键字的作⽤),可能初学C51时有点不好懂也不好记。

没关系,我们马上就可以看到对应“*”前后不同的关键字的使⽤在编译时出现什么情况。

你知道嵌入式C语言中各变量存储的位置吗?

你知道嵌入式C语言中各变量存储的位置吗?

你知道嵌入式C语言中各变量存储的位置吗?
在举行C/C++编程时,需要程序员对内存的了解比较精准。

常常需要操作的内存可分为以下几个类别:
1、栈区(stack)—由编译器自动分配释放,存放函数的参数值,局
部变量的值等。

其操作方式类似于数据结构中的栈。

2、堆区(heap)—普通由程序员分配释放,若程序员不释放,程序
结束时可能由OS回收。

注重它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。

3、全局区(静态区)(static)—,全局变量和静态变量的存储是放
在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。

4、文字常量区—常量字符串就是放在这里的。

5、程序代码区—存放函数体的二进制代码。

以下是一段实际解释的程序代码:这是一个前辈写的,十分具体。

int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b; 栈
char s[] = "abc"; 栈
char *p2; 栈
char *p3 = "123456"; 123456在常量区,p3在栈上。

static int c =0;全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得来得10和20字节的区域就在堆区。

strcpy(p1, "123456"); 123456放在常量区,编译器可能会将它与p3
第1页共3页。

局部变量、全局变量、静态变量的含义及存储位置

局部变量、全局变量、静态变量的含义及存储位置

局部变量、全局变量、静态变量的含义及存储位置1.局部变量在⼀个函数内部定义的变量是内部变量,它只在本函数范围内有效,也就是说只有在本函数内才能使⽤它们,在此函数以外时不能使⽤这些变量的,它们称为局部变量。

局部变量保存在动态数据区的栈中,只有在所在函数被调⽤时才动态地为变量分配存储单元。

1).主函数main中定义的变量也只在主函数中有效.2).不同函数中可以使⽤名字相同的变量,它们代表不同的对象,互不⼲扰.3).形参也是局部变量.4).在复合语句中定义的局部变量,这些变量只在本复合语句中有效.2.全局变量在函数外定义的变量是外部变量,外部变量是全局变量,全局变量可以为本⽂件中其它函数所共⽤,它的有效范围从定义变量的位置开始到本源⽂件结束。

全局变量位于静态数据区中。

1).设全局变量的作⽤:增加了函数间数据联系的渠道.2).建议不再必要的时候不要使⽤全局变量,因为a.全局变量在程序的全部执⾏过程中都占⽤存储单元.b.它使函数的通⽤性降低了3).如果外部变量在⽂件开头定义,则在整个⽂件范围内都可以使⽤该外部变量,如果不再⽂件开头定义,按上⾯规定作⽤范围只限于定义点到⽂件终了.如果在定义点之前的函数想引⽤该外部变量,则应该在该函数中⽤关键字extern作外部变量说明.4).如果在同⼀个源⽂件中,外部变量与局部变量同名,则在局部变量的作⽤范围内,外部变量不起作⽤.3.静态变量静态变量并不是说其就不能改变值,不能改变值的量叫常量。

其拥有的值是可变的,⽽且它会保持最新的值。

说其静态,是因为它不会随着函数的调⽤和退出⽽发⽣变化。

即static局部变量只被初始化⼀次,下⼀次依据上⼀次结果值;静态变量的作⽤范围要看静态变量的位置,如果在函数⾥,则作⽤范围就是这个函数。

静态变量属于静态存储⽅式,其存储空间为内存中的静态数据区(在静态存储区内分配存储单元),该区域中的数据在整个程序的运⾏期间⼀直占⽤这些存储空间(在程序整个运⾏期间都不释放),也可以认为是其内存地址不变,直到整个程序运⾏结束(相反,⽽auto⾃动变量,即动态局部变量,属于动态存储类别,占动态存储空间,函数调⽤结束后即释放)。

变量的数据类型

变量的数据类型

变量的数据类型标题:变量的数据类型引言概述:在计算机编程中,变量是存储数据的容器。

每一个变量都有其特定的数据类型,用于定义变量可以存储的数据的种类和范围。

本文将介绍变量的数据类型,并详细阐述每种数据类型的特点和用途。

一、基本数据类型1.1 整型(int)- 整型变量用于存储整数值,包括正整数、负整数和零。

- 整型变量的范围取决于所使用的编程语言和计算机架构。

1.2 浮点型(float)- 浮点型变量用于存储带有小数部份的数值。

- 浮点型变量的精度和范围也取决于所使用的编程语言和计算机架构。

1.3 字符型(char)- 字符型变量用于存储单个字符,如字母、数字或者特殊字符。

- 字符型变量在内存中以ASCII码或者Unicode码的形式存储。

二、复合数据类型2.1 数组(array)- 数组是一种存储相同类型数据的集合。

- 数组的元素可以通过索引访问,索引从0开始。

2.2 字符串(string)- 字符串是一串字符的序列,用于存储文本数据。

- 字符串变量可以进行拼接、截取和比较等操作。

2.3 结构体(struct)- 结构体是一种自定义的复合数据类型,可以包含多个不同类型的变量。

- 结构体可以用于表示复杂的数据结构,如学生信息、员工信息等。

三、指针类型3.1 指针(pointer)- 指针变量用于存储内存地址。

- 指针可以指向其他变量或者数据结构,在程序中进行间接访问。

3.2 引用(reference)- 引用是一种特殊的指针,用于直接访问其他变量的值。

- 引用可以简化代码,提高程序的效率。

3.3 空指针(null pointer)- 空指针是指不指向任何有效内存地址的指针。

- 空指针在程序中常用于表示变量未初始化或者指向空对象。

四、枚举类型4.1 枚举(enum)- 枚举类型用于定义一组具有名称的常量。

- 枚举常量可以用于增加代码的可读性和可维护性。

4.2 位字段(bit field)- 位字段是一种特殊的枚举类型,用于压缩存储多个布尔值。

C++静态变量,常量的存储位置你真的了解吗

C++静态变量,常量的存储位置你真的了解吗

C++静态变量,常量的存储位置你真的了解吗⽬录引⾔C++对内存的划分如何落实在Linux上⾃由存储区和堆之间的问题栈常量区静态存储区静态局部变量静态局部变量、静态全局变量、全局变量的异同总结引⾔在动态内存的博客中,我提到:在Linux 内存管理的博客中,我提到:尽管都有尽可能完全的描述,并且两者⼤致意思没有冲突。

⽽之所以令我⼀直感到略有不同,越看越迷糊的原因是:第⼀张图讲的其实是C++在概念上对内存的划分,第⼆张图讲的是Linux对虚拟内存进⾏的划分。

前者是概念上的,也是C++程序在运⾏时会切实执⾏的,⽽后者就是在Linux系统上对前者概念的具象化!下⾯进⾏进⼀步分析。

C++对内存的划分如何落实在Linux上C++其实将内存划分为两种:动态存储区、静态存储区。

第⼀张图对动态存储区进⾏了进⼀步划分——堆、栈。

⽽⽹上其他博客可能还会对动态存储区进⾏进⼀步划分——堆、栈、⾃由存储区。

并对静态存储区进⾏进⼀步划分——常量存储区、全局/静态存储区。

可谓是五花⼋门,我们不妨先做个归拢:⾃由存储区和堆之间的问题这篇博客分析地很详细C++ ⾃由存储区是否等价于堆?,我引⽤其中⼀些内容进⾏分析:在概念上我们是这样区分两者的:malloc 在堆上分配的内存块,使⽤ free 释放内存。

new 所申请的内存则是在⾃由存储区上,使⽤ delete 来释放。

那么物理上,⾃由存储区与堆是两块不同的内存区域吗?它们有可能相同吗?基本上,所有的 C++编译器默认使⽤堆来实现⾃由存储,也即是缺省的全局运算符 new 和 delete 也许会按照 malloc 和 free 的⽅式来被实现,这时藉由 new 运算符分配的对象,说它在堆上也对,说它在⾃由存储区上也正确。

但程序员也可以通过重载操作符,改⽤其他内存来实现⾃由存储,例如全局变量做的对象池,这时⾃由存储区就区别于堆了。

总结:⾃由存储是 C++ 中通过 new 与 delete 动态分配和释放对象的抽象概念,⽽堆(heap)是 C语⾔和操作系统的术语,是操作系统维护的⼀块动态分配内存。

java静态变量与全局变量区别及存放位置

java静态变量与全局变量区别及存放位置

java静态变量与全局变量区别及存放位置java静态变量存放区静态的意思:只有⼀份!不存在拷贝!虚拟机内存分为四个区:stack segment,heap segment,data segment,code segment;stack 区存放函数参数和局部变量;heap 区存放对象;data 区存放static 的变量或者字符串常量;code 区存放类中的⽅法;所以,静态变量是存放在data区的静态变量属于类的属性。

⾄于他放在那⾥?有⼈说的是静态区。

我不知道到底有没有这个翻译。

但是深⼊jvm⾥是是翻译为⽅法区的。

虚拟机的体系结构:堆,⽅法区,本地⽅法栈,pc寄存器。

⽽⽅法区保存的就是⼀个类的模板,堆是放类的实例的。

栈是⼀般来⽤来函数计算的。

随便找本计算机底层的书都知道了。

栈⾥的数据,函数执⾏完就不会存储了。

这就是为什么局部变量每⼀次都是⼀样的。

就算给他加⼀后,下次执⾏函数的时候还是原来的样⼦。

static函数与普通函数有什么区别:static函数在内存中只有⼀份,普通函数在每个被调⽤中维持⼀份拷贝全局变量和静态变量的区别:全局变量在整个⼯程⽂件内都有效;静态全局变量只在定义它的⽂件内有效;静态局部变量只在定义它的函数内有效,只是程序仅分配⼀次内存,函数返回后,该变量不会消失;局部变量在定义它的函数内有效,但是函数返回后失效。

全局变量(外部变量)的说明之前再冠以static就构成了静态的全局变量。

全局变量本⾝就是静态存储⽅式,静态全局变量当然也是静态存储⽅式。

这两者在存储⽅式上并⽆不同。

这两者的区别虽在于⾮静态全局变量的作⽤域是整个源程序,当⼀个源程序由多个源⽂件组成时,⾮静态的全局变量在各个源⽂件中都是有效的。

⽽静态全局变量则限制了其作⽤域,即只在定义该变量的源⽂件内有效,在同⼀源程序的其它源⽂件中不能使⽤它。

由于静态全局变量的作⽤域局限于⼀个源⽂件内,只能为该源⽂件内的函数公⽤,因此可以避免在其它源⽂件中引起错误。

python中变量的存储机制

python中变量的存储机制

python中变量的存储机制Python是一种高级编程语言,它具有简洁、易读、易学的特点,因此在近年来得到了广泛的应用和推广。

在Python中,变量是程序中存储数据的一种方式,它可以用来保存各种类型的数据,如整数、浮点数、字符串等。

然而,对于初学者来说,了解Python中变量的存储机制可能会有些困惑。

本文将介绍Python中变量的存储机制,帮助读者更好地理解和使用Python。

在Python中,变量是用来存储数据的容器。

当我们创建一个变量时,实际上是在内存中分配了一块空间来存储数据。

这个空间被称为变量的内存地址,我们可以通过变量名来访问这个内存地址。

例如,当我们创建一个整数变量x,并将其赋值为10时,Python会在内存中分配一块空间来存储整数10,并将这个空间的内存地址与变量名x关联起来。

在Python中,变量的存储机制可以分为两种情况:可变类型和不可变类型。

可变类型的变量在内存中的值可以被修改,而不可变类型的变量在内存中的值是不可修改的。

对于不可变类型的变量,当我们对其进行赋值操作时,实际上是创建了一个新的对象,并将变量名与新对象的内存地址关联起来。

例如,当我们将一个整数变量x赋值为20时,Python会创建一个新的整数对象20,并将变量名x与新对象的内存地址关联起来。

原来的整数对象10仍然存在于内存中,但由于没有变量与其关联,所以无法访问到它。

对于可变类型的变量,当我们对其进行赋值操作时,实际上是修改了对象在内存中的值,而不是创建一个新的对象。

例如,当我们创建一个列表变量lst,并将其赋值为[1, 2, 3]时,Python会在内存中创建一个列表对象,并将变量名lst与该对象的内存地址关联起来。

当我们对列表进行修改操作时,如添加元素、删除元素等,实际上是在修改列表对象在内存中的值,而不是创建一个新的列表对象。

在Python中,变量的存储机制还涉及到引用计数和垃圾回收机制。

引用计数是一种跟踪对象被引用次数的机制,当一个对象的引用计数为0时,说明没有变量与其关联,该对象将被垃圾回收机制回收。

局部变量、全局变量、堆、堆栈、静态和全局变量

局部变量、全局变量、堆、堆栈、静态和全局变量

局部变量、全局变量、堆、堆栈、静态和全局变量一般全局变量存放在数据区,局部变量存放在栈区,动态变量存放在堆区,函数代码放在代码区。

---------------------------------------------------------------栈区是普通的栈数据结构,遵循LIFO后进先出的规则,局部变量安排在那里是ASM时就规定的,这样可以在一个函数结束后平衡堆栈,操作简单,效率高堆(动态区)在这里应当叫堆栈(不要和数据结构中的堆搞混)是程序在编译时产生的一块用于产生动态内存分配使用的块,操作比较栈要麻烦许多,在分配时要判断最优的地址(防止产生无用的内存碎片(由于屡次的NEW和DELETE产生的夹在两块使用中内存中的空余小内存(不容易被分配))),分配和回收时的效率比栈低多了---------------------------------------------------------------栈是系统提供的功能,特点是快速高效,缺点是有限制,数据不灵活;而堆是函数库提供的功能,特点是灵活方便,数据适应面广泛,但是效率>有一定降低。

栈是系统数据结构,对于进程/线程是唯一的;堆是函数库内部数据结构,不一定唯一。

不同堆分配的内存无法互相操作。

栈空间分静态分配和动态分配两种。

静态分配是编译器完成的,比如自动变量(auto)的分配。

动态分配由malloca函数完成。

栈的动态分配无需释放(是自动的),也就没有释放函数。

为可移植的程序起见,栈的动态分配操作是不被鼓励的!堆空间的分配总是动态的,虽然程序结束时所有的数据空间都会被释放回系统,但是精确的申请内存/ 释放内存匹>配是良好程序的基本要素。

堆是程序员管理的,栈是系统管理的.另外关于静态和全局的一些问题:静态变量的特点:1、一次存储:静态局部变量只被初始化一次,下一次初始化根据上一次的结果值,有点类似于c++中类的静态成员变量,即无论该类型生成多少个实例对象,所有的对象共用一个静态变量,到这里就是无论这个函数调用多少次,该静态变量只初始化一次,并没有因为超出其生存期而被销毁,只是外部不可见而已,用个例子说明之:void fun1( int v ){static int value = v;static int value = v;}int main( int arc, char*args[ ]){fun1( 50 );fun1( 100 );}执行的结果是:value : 50 value : 50说明在第二次调用fun1( )时的初始化value的采用的是上一次value的值,value在静态区的存储空间并没有因为fun1( )的结束而被释放,即体现了一次存储;2、作用域限定:静态修饰的作用域限定功能同时体现在函数与变量上;a)对于函数而言,任何用static修饰的函数,其作用域仅为当前源文件,而对外部来说这个函数是不可见的,即只有和其在同一源文件中的函数才能调用这个静态函数;反过来说,如果一个函数仅仅被同一源文件中的其他函数调用,那么这个函数应该声明为静态的,这样做的好处在于:可以一定程度上的解决不同源文件之间函数的命名冲突问题;b)对于变量而言,static修饰的全局变量,只在当前源文件中有效,对外部不可见,外部文件不能够引用;顾名思义,全局变量是指能够在全局引用的变量,相对于局部变量的概念,也叫外部变量;同静态变量一样,全局变量位于静态数据区,全局变量一处定义,多处引用,用关键字“extern”引用“外部”的变量。

STM32堆栈大小详解以及变量存储位置

STM32堆栈大小详解以及变量存储位置

STM32堆栈大小详解以及变量存储位置栈增长和大端/小端问题是和CPU相关的两个问题.1,首先来看:栈(STACK)的问题.函数的局部变量,都是存放在'栈'里面,栈的英文是:STACK.STACK的大小,我们可以在stm32的启动文件里面设置,以战舰stm32开发板为例,在startup_stm32f10x_hd.s里面,开头就有:Stack_Size EQU 0x00000800表示栈大小是0X800,也就是2048字节.这样,CPU处理任务的时候,函数局部变量做多可占用的大小就是:2048字节,注意:是所有在处理的函数,包括函数嵌套,递归,等等,都是从这个'栈'里面,来分配的.所以,如果一个函数的局部变量过多,比如在函数里面定义一个u8 buf[512],这一下就占了1/4的栈大小了,再在其他函数里面来搞两下,程序崩溃是很容易的事情,这时候,一般你会进入到hardfault....这是初学者非常容易犯的一个错误.切记不要在函数里面放N多局部变量,尤其有大数组的时候!对于栈区,一般栈顶,也就是MSP,在程序刚运行的时候,指向程序所占用内存的最高地址.比如附件里面的这个程序序,内存占用如下图:图中,我们可以看到,程序总共占用内存:20 2348字节=2368=0X940那么程序刚开始运行的时候:MSP=0X2000 0000 0X940=0X2000 0940.事实上,也是如此,如图:图中,MSP就是:0X2000 0940.程序运行后,MSP就是从这个地址开始,往下给函数的局部变量分配地址.再说说栈的增长方向,我们可以用如下代码测试://保存栈增长方向//0,向下增长;1,向上增长.static u8 stack_dir;//查找栈增长方向,结果保存在stack_dir里面.void find_stack_direction(void){static u8 *addr=NULL; //用于存放第一个dummy的地址。

STM32 变量存储在片内FLASH的指定位置

STM32 变量存储在片内FLASH的指定位置

STM32 变量存储在片内FLASH的指定位置在这里以STM32L4R5为例(官方出的DEMO板),将变量存储在指定的片内FLASH地址(0x081F8000)。

一、MDK Keil软件操作
如上图所示,采用上述方式,可以将version和version1分别存储在STM32单片机片内FLASH 的0x081F8000和0x081F8010地址。

对于嵌入式系统或者单片机而言,通常会将一系列的配置文件存储在一个指定的区域(section)。

也就是说,某种类型的变量存储在一个指定的区域内。

在这里,就要修改STM32的链接文件了。

下图为STM32的默认链接文件配置。

修改Scatter File文件。

添加下图中红框内的代码,该代码的含义是定义一个区域RW_IROM2(段属性为UNINIT_FIXED_LOC),该区域的起始地址为0x081F8000,大小为0x00008000。

.ANY(UNINIT_FIXED_LOC)表示存储任何段属性为
UNINIT_FIXED_LOC的数据。

取消1处的勾选,在2处选择自己修改过后的Scatter File。

如此,在编程时,只需如此定义相应的数据类型。

在编译通过后,查看.map文件,可以看到0x081f8000处存储了0x0000000c 大小的数据,段属性为UNINIT_FIXED_LOC
二、IAR操作
在链接文件(.icf)中添加如下代码
三、注意
该文是将变量存储在STM32片内FLASH中,故对变量进行操作时,需要按照片内FLASH的操作方式进行,即先解锁,然后修改,再加锁。

C语言-常量和变量的存储位置

C语言-常量和变量的存储位置

C语⾔-常量和变量的存储位置C语⾔ - 常量和变量的存储位置⽬录〇、环境项值语⾔C编译器gcc编译环境x86_64-linux-gnu⼀、常量和变量的存储位置1.1 实验⽅法静态观察:对编译得到的可执⾏⽂件进⾏分析动态观察:运⾏时获取变量的地址,并分析变量在进程地址空间的位置1.2 ⽰例程序⽰例程序1#include <stdio.h>#include <unistd.h>static int local_static_uninit;static int local_static_init = 0x88;static int localarr_static_uninit[1024];static int localarr_static_init[1024] = {1,2,3};int global_uninit;int gloabl_init = 0x88;int globalarr_uninit[1024];int globalarr_init[1024] = {1,2,3};int add(int a, int b){static int infun_static_uninit;static int infun_static_init = 0x88;static int infunarr_static_uninit[1024];static int infunarr_static_init[1024] = {1,2,3};int c;int d = 0;int e = a + b;printf ("&local_static_uninit=%p\n""&local_static_init=%p\n""&localarr_static_uninit[0]=%p\n""&localarr_static_init[0]=%p\n""&global_uninit=%p\n""&gloabl_init=%p\n""&globalarr_uninit[0]=%p\n""&globalarr_init[0]=%p\n""&infun_static_uninit=%p\n""&infun_static_init=%p\n""&infunarr_static_uninit[0]=%p\n""&infunarr_static_init[0]=%p\n""&a=%p\n""&b=%p\n""&c=%p\n""&d=%p\n",&local_static_uninit,&local_static_init,&localarr_static_uninit[0],&localarr_static_init[0],&global_uninit,&gloabl_init,&globalarr_uninit[0],&globalarr_init[0],&infun_static_uninit,&infun_static_init,&infunarr_static_uninit[0],&infunarr_static_init[0],&a, &b, &c, &d);while (1){sleep (5);}return e;}int main(){add(1,2);return 0;}⽂件布局:运⾏输出:./a.out&local_static_uninit=0x6040e0&local_static_init=0x601060&localarr_static_uninit[0]=0x604100&localarr_static_init[0]=0x601080&global_uninit=0x606120&gloabl_init=0x602080&globalarr_uninit[0]=0x606140&globalarr_init[0]=0x6020a0&infun_static_uninit=0x605100&infun_static_init=0x6030a0&infunarr_static_uninit[0]=0x605120&infunarr_static_init[0]=0x6030c0&a=0x7ffd0ee30b1c&b=0x7ffd0ee30b18&c=0x7ffd0ee30b2c&d=0x7ffd0ee30b30进程地址布局:cat /proc/2446/maps00400000-00401000 r-xp 00000000 fc:00 130819 /home/ttt/test/a.out00600000-00601000 r--p 00000000 fc:00 130819 /home/ttt/test/a.out00601000-00605000 rw-p 00001000 fc:00 130819 /home/ttt/test/a.out00605000-00608000 rw-p 00000000 00:00 0007cf000-007f0000 rw-p 00000000 00:00 0 [heap]7f54a3458000-7f54a3618000 r-xp 00000000 fc:00 659982 /lib/x86_64-linux-gnu/libc-2.23.so 7f54a3618000-7f54a3818000 ---p 001c0000 fc:00 659982 /lib/x86_64-linux-gnu/libc-2.23.so 7f54a3818000-7f54a381c000 r--p 001c0000 fc:00 659982 /lib/x86_64-linux-gnu/libc-2.23.so 7f54a381c000-7f54a381e000 rw-p 001c4000 fc:00 659982 /lib/x86_64-linux-gnu/libc-2.23.so 7f54a381e000-7f54a3822000 rw-p 00000000 00:00 07f54a3822000-7f54a3848000 r-xp 00000000 fc:00 659993 /lib/x86_64-linux-gnu/ld-2.23.so 7f54a3a3c000-7f54a3a3f000 rw-p 00000000 00:00 07f54a3a47000-7f54a3a48000 r--p 00025000 fc:00 659993 /lib/x86_64-linux-gnu/ld-2.23.so 7f54a3a48000-7f54a3a49000 rw-p 00026000 fc:00 659993 /lib/x86_64-linux-gnu/ld-2.23.so 7f54a3a49000-7f54a3a4a000 rw-p 00000000 00:00 07ffd0ee11000-7ffd0ee32000 rw-p 00000000 00:00 0 [stack]7ffd0eff3000-7ffd0eff6000 r--p 00000000 00:00 0 [vvar]7ffd0eff6000-7ffd0eff8000 r-xp 00000000 00:00 0 [vdso]ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]1.3 结果分析1.3.1 运⾏时结果源⽂件中的全局变量,包括普通全局变量、静态全局变量,不论是否初始化,均在程序段(可写数据段)函数内部的静态变量,不论是否初始化,均在程序段(可写数据段)。

C语言中局部变量和全局变量等在内存中的存放位置

C语言中局部变量和全局变量等在内存中的存放位置

C语言中局部变量和全局变量变量的存储类别(static,extern,auto,register)8.8局部变量和全局变量在讨论函数的形参变量时曾经提到,形参变量只在被调用期间才分配内存单元,调用结束立即释放。

这一点表明形参变量只有在函数内才是有效的,离开该函数就不能再使用了。

这种变量有效性的范围称变量的作用域。

不仅对于形参变量,C语言中所有的量都有自己的作用域。

变量说明的方式不同,其作用域也不同。

C语言中的变量,按作用域范围可分为两种,即局部变量和全局变量。

8.8.1局部变量局部变量也称为内部变量。

局部变量是在函数内作定义说明的。

其作用域仅限于函数内,离开该函数后再使用这种变量是非法的。

例如:int f1(int a) /*函数f1*/{int b,c;……}a,b,c有效int f2(int x) /*函数f2*/{int y,z;……}x,y,z有效main(){int m,n;……}m,n有效在函数f1内定义了三个变量,a为形参,b,c为一般变量。

在f1的范围内a,b,c有效,或者说a,b,c变量的作用域限于f1内。

同理,x,y,z的作用域限于f2内。

m,n的作用域限于main函数内。

关于局部变量的作用域还要说明以下几点:1)主函数中定义的变量也只能在主函数中使用,不能在其它函数中使用。

同时,主函数中也不能使用其它函数中定义的变量。

因为主函数也是一个函数,它与其它函数是平行关系。

这一点是与其它语言不同的,应予以注意。

2)形参变量是属于被调函数的局部变量,实参变量是属于主调函数的局部变量。

3)允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。

如在前例中,形参和实参的变量名都为n,是完全允许的。

4)在复合语句中也可定义变量,其作用域只在复合语句范围内。

例如:main(){int s,a;……{int b;s=a+b;……/*b作用域*/}……/*s,a作用域*/}【例8.12】main(){int i=2,j=3,k;{int k=8;printf("%d\n",k);}printf("%d\n",k);}本程序在main中定义了i,j,k三个变量,其中k未赋初值。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

我相信大家都有过这样的经历,在面试过程中,考官通常会给你一道题目,然后问你某个变量存储在什么地方,在内存中是如何存储的等等一系列问题。

不仅仅是在面试中,学校里面的考试也会碰到同样的问题。

如果你还不知道答案,请接着往下看。

接下来,我们将在Linux操作系统上,以GCC编译器为例来讲解变量的存储。

在计算机系统中,目标文件通常有三种形式:
1.可重定位的目标文件:包含二进制代码和数据,与其他可重定位目标文件合并起来,创建一个可执行目标文件。

2.可执行的目标文件:包含二进制代码和数据,其形式可以被直接拷贝到存储器中并执行
3.共享目标文件:一种特殊的可重定位目标文件,即我们通常所说的动(静)态链接库
一个典型的可重定位目标文件如下图所示:
高地址
图1典型的ELF可重定位目标文件(数字代表索引)
夹在ELF头和节头部表之间的都是节(section),各个节的意思如下:
对于static类型的变量,gcc编译器在.data和.bss中为每个定义分配空间,并在.symtab节中创建一个有唯一名字的本地链接器符号。

对于malloc而来的变量存储在堆(heap)中,局部变量都存储在栈(stack)中。

下面我们以实际的例子来分析变量的存储:
根据以上题目和理论知识,我们可以推断出:
我们将从汇编代码和符号表中来分析以上答案是否正确。

我们首先来看该程序的汇编代码:
通过以上汇编代码可以发现,z和b在.data段,main和swap在.text段,a和c在.bss段,x,y,temp在stack中,printf 函数所打印的字符串在.rodata中。

下面我们在通过符号表来解释变量的存储。

每个可重定位目标文件都有一个符号表,它包含该文件所定义和引用的符号的信息。

在链接器的上下文中,有三种不同的符号:
1.由该文件定义并能被其他模块引用的全局符号。

即非静态的C函数和非静态的全局变量,如程序中的a,z,swap。

2.由其他模块定义并被该文件引用的全局符号。

用extern关键字所定义的变量和函数。

3.只被该文件定义和引用的本地符号。

用static关键字定义的函数和变量。

如程序中的b和c。

该程序所对应的符号表如图所示:
图2符号表
首先,我们解释上图中各字段的含义:
对于变量b和z,Ndx索引为3,我们观察图1,不难发现索引3对应的是.data段。

变量c对应的索引为4(.bss段),变量a对应的索引是COM,最终当该程序被链接时,它将做为一个.bss目标分配。

我们从反汇编代码中,对于变量a和c都是.comm (反汇编代码中以“.”开头的行,是指导汇编器和链接器运行的命令):
注意:a所对应的Bind为GLOBAL,即为全局变量,虽然变量c也在.bss段中,但Bind却是LOCAL,则为本地变量。

.data段中的变量b和c也是类似的情况。

swap和main都在索引1所对应的.text段中。

由于printf是在库中所定义的,所以索引为UND。

符号表中不包含对应于本地非静态程序变量中的任何符号。

这些符号是在栈中被管理的,所以符号表中没有出现x,y,temp符号。

相信大家读完这篇文章以后,再也用不着对类似的题目胆战心惊了。

相关文档
最新文档