‘壹’ 程序的局部变量 全局变量 动态申请数据分别存储在什么地方
程序的局部变量 全局变量 动态申请数据分别存储在什么地方?
量的类别:
根据作用域可分为全局变量和局部变量。
根据生存周期可分为静态存储方式和动态存储方式,具体地又分为自动的(auto)、静态的(static)、寄存器的(register)、外部的(extern)。
静态存储方式是指在程序运行期间分配固定的存储空间的方式,动态存储方式是在程序运行期间根据需要进行动态的分配存储空间的方式。
每一个变量均有作用域和存储类别两个属性,这些属性共同用于描述一个变量,这些不同类型的变量与存储位置的关系如下:
外部变量(全局变量)、静态外部变量、静态局部变量存储在静态存储区。
自动局部变量(局部变量默认为自动局部变量)、函数形参存储在动态存储区,不论是静态存储区还是动态存储区均属于内存中的用户区。
但是,寄存器变量是存储在CPU寄存器中的而不是内存中。
首先说明一下与作用域相关的几个属性:
局部变量:在一个函数内部定义的变量是内部变量,它只在本函数范围内有效,也就是说只有在本函数内才能使用它们,在此函数以外是不能使用这些变量的,这种类型的变量就称为“局部变量”。
全局变量:在函数外定义的变量,可以为本源文件中其它函数所公用,有效范围为从定义变量的位置开始到本源文件结束,这种类型的变量就称为“全局变量”。
接下来说明一下与存储类型相关的几个属性:
atuo:在声明局部变量时,若不指定 static,默认均是 auto,这类变量都是动态分配存储空间的,数据存储在动态存储区中。
static:在声明局部变量时,使用关键字 static 将局部变量指定为“静态局部变量”,这样在函数调用结束后不消失而保留原值,即占用的存储单元不释放,在下一次函数调用时,该变量已有值就是上次函数调用结束时的值。
register:在声明动态局部变量或者函数形参时,可将变量声明为register,这样编译系统就会为变量分配一个寄存器而不是内存空间,通过这种方式可提升对某些局部变量频繁调用的程序的性能。(寄存器运算速度远高于内存)
extern:用于扩展全局变量的作用域,比如如果函数想引用一个外部变量,但该外部变量在该函数后定义,那么这个函数需要使用 extern 来声明变量,这样才能使用在该函数后面定义的全局变量。此外,extern 还可以在多文件的程序中声明外部变量。
由于变量从不同维度划分,形成了多种错综复杂的关系,在学习编程的时候需要重点关注。
‘贰’ 编写程序过程中要引用变量的存储地址时,可以通过什么来获得
编写程序过程中要引用变量的存储地址时,以通过好腔局程序计数器PC来获得。
名字编译后会被映射成数据的地址(可以是绝对地址或者偏移地址),如何通过地址来访问数据,本身就是代码的一部分。而外部变量的地址,在编译的时候还不能完全确定,就先空着,等链接的时候再进行回友让填。
引用变量的存储地址:
程序中用到的所有地址,都不是真实的内存地址,只是虚拟内存地址。程序用到虚拟内存,分成一页页,比如每页是 4K。有些页确实存储在真实的内存当中,但圆坦有些页存储在磁盘当中,有些页就单纯空着。操作系统和硬件会将虚拟内存映射成真实的内存,具体的程序不用关心。
‘叁’ 51单片机定义变量时默认是存储到哪里的
未显式声明的情况下,变量会根据Memory Model的设置,默认分配在指定的存储区。
Small模式:默认分配在data区
Compact模式:默认分配在pdata区
Large模式:默认分配在xdata区
新建工程默认都是Small模式,所以未显式声明存储区域的变量都会分配在data区的。所以才会容易出现data区挤爆、编译器跳着脚让你把变量分到idata区去……
‘肆’ 局部变量 全局变量 动态变量分别存储什么位置
在C语言里面,局部变量,全局变量都是存贮在栈(stack)里面的,
而所有用malloc和new这种操作符动态分配的空间则都是存贮在堆(mp)里面的,
举个简单的例子:
int *ptr;
ptr =(int*)malloc(100*sizeof(int));
这两句中,ptr这个指针变量是存贮在栈里面,但是他所指向的内容则是在堆里面。明白了吗
‘伍’ 程序的局部变量 全局变量 动态申请数据分别存储在什么地方
程序的局部变量全局变量动态申请数据分别存储在栈里。
普通局部变量在堆栈空间上分配,当局部变量的函数被多次调用时,局部变量每次在堆栈上的位置都不相同。还可以在堆上动态分配局部变量(malloc),但是要记住在耗尽堆空间后释放zd。
内存分配上的栈空间时要注意内存的,不能分配太多的内存。如果堆栈中的空间小于请求的空间大小,则系统将显示堆栈溢出并给出相应的异常信息。但堆不同,堆可分配空间很大。
(5)链接脚本指定变量存储位置扩展阅读:
注意事项:
对局部变量进行分类
1.位置:编译器将静态局部变量放在全局存储区域中。数据,因此尽管它是本地的,但它存在于程序的整个生命周期中(它在定义时产生,并随着程序的结束而结束)。
2.访问权限:静态局部变量只能由其作用域内的变量或函数访问。也就是说,尽管它将存在于程序的整个生命周期中,但是其他函数和源文件不能访问它,因为它是静态的。
3.值:如果用户没有初始化静态局部变量,编译器会自动将其赋值为0,每次调用静态局部变量时都会使用最后一次调用后的值。
‘陆’ 嵌入式系统为什么自定义链接脚本
既然你说嵌入式系统,我就不多废话了,直接说链接脚本,如果有不懂得欢迎提问,我大四和你一样在学这方面内容。
如果我们不自己定义的话,编译使用的是内部默认的链接脚本,链接脚本的本质就是说明程序的各个段(数据段,代码段,bss段=》没有被初始化的全局变量)保存在内存的什么位置,这里涉及运行域和装载域,我们把程序烧录到flash中这时运行程序所在的地址称之为装载域(flash中的地址),由于程序中包含数据段和bss段他们是可以修改的,因此要把bss段数据段从装载域(flash)拷贝到在ram中(称之为运行域),当程序要访问这个变量时,通过链接脚本定义的地址信息可以知道我们在内存的哪个地址访问这个变量,本质就是指定运行域的地址,这就是链接脚本的本质,我们也可以把程序拷贝到内存中,在内存中运行,但是要靠链接脚本告诉我们程序(代码段)在哪里,变量在哪里(数据段),好让编译器自动的给我们算好变量的地址信息,至于为什么要自定义的话,根据要求板子打硬件环境定制的,例如我们的arm板子要跑linux,我们的程序烧录到flash中,然后要拷贝到内存中,但是默认的链接脚本怎么知道我们的各个段信保存在内存的哪里?这时候需要我们自己定义链接脚本。