linux C编程(二)数据与函数的存储类型和内存管理

本篇文章为C语言基础系列~~

变量的存储类型
变量的存储类型主要定义了变量的作用域,连接属性,存储属性。

1. 存储属性
1.1 作用域
表示该变量可以被使用的区域。分为代码块作用域,函数原型作用域,文件作用域。 
如对于下面的一个main.c而言,var_ file作用域为整个文件main.c,var_ function作用域为main函数,var _code _block作用域仅为for循环的{}中。作用域不重合的两个变量可以重名。

#include <stdio.h>
int var_file = 0;
int main()
{
    int var_function = 0;
    int i = 0;
    for (i = 0;i < 10;i++)
    {
        int var_code_block = 0;
        ...
    }
}

1.2 链接属性
主要表示该变量是否能够被外部文件所使用,即链接。分为外部链接,内部链接,空链接。外部链接表示该变量能够被任意外部文件里的函数所使用,内部链接表示该变量仅能够被文件内部的任意函数所使用。

代码块作用域和函数作用域的变量链接属性只能为空链接。 
文件作用域的变量可以默认为外部链接。当其加入static限定符时为内部链接。

外部链接和内部链接属性只有在多文件应用中才起作用。

1.3 时间属性
主要表示该变量在内存中的生存周期。分为静态周期和自动周期。静态周期的变量在程序运行期间一直在内存中存在,自动周期的变量退出作用域后自动注销。 
∙∙具有文件作用域的变量具有静态周期属性,与其链接属性无关。 
∙∙具有函数和代码块作用域的变量默认具有自动周期属性,当其加入static限定符时,具有静态周期属性

属性总结: 
(1)局部变量(函数作用域和代码块作用域),全局变量(文件作用域) 
(2)局部变量一直为空链接,static可以限定全局变量的链接属性 
(3)全局变量具有静态生存周期,static可以限定局部变量的生存周期

2. 四种存储类型
主要由auto,register,static,extern四种存储类型

auto
具有自动周期属性,函数作用域或者代码块作用域,空链接属性。 
不会自动初始化,为随机值。 
在函数和代码块内部,auto为默认缺省属性。(函数外部不缺省!)

register
使用该存储方式定义时,是在请求将该变量放在寄存器中,这样能够操作的更快。但这只是一个请求,是否能被满足还需要考虑当时的寄存器和内存的使用情况。 
另外,register不能够用来定义一些类似于double型的数据,因为double占用64字节,没有与之对应的寄存器可以存储。

static
作用在全局变量(文件作用域,静态生存周期)上,表示使其具有内部链接属性,否则具有外链接属性 
作用在局部变量上(函数或代码块作用域,空链接),表示使其具有静态生存周期,否则具有自动生存周期 
也即: 
全局变量:文件作用域,外链接属性,静态生存周期 
局部变量:局部作用域,空链接属性,自动生存周期 
静态全局变量:文件作用域,内链接属性,静态生存周期 
静态局部变量:局部作用域,空链接属性,静态生存周期

extern
作用在变量上,表示声明在该变量作用域外部定义的变量,适用于全局变量与局部变量

extern并不改变变量的存储属性,只是在多文件编译时,和链接属性共同使用

注意以下的不同,extern一般只在变量声明的时候使用

extern int age = 0;//变量的定义,一般不用
extern int age;//变量的声明
1
2
函数的存储类型
同变量一样,函数也具有存储类型,主要有两种:static与extern 
static表示函数的作用域为本文件,extern表示函数的作用域为任意外部文件。static函数的存在是为了增加私有性,避免函数命名的冲突。 
与变量中extern只在声明时起作用不同,函数的存储类型在定义和声明的时候都要显示写出(extern的定义和声明为缺省状态,可以不写)

C程序运行时的内存分配
上述的四中存储类型一旦确定,应用程序在执行时数据的内存分配就必须满足相应固定的规则。

操作系统中的应用程序
对于操作系统中的应用而言,该规则由操作系统根据系统当时所处的状态来分配;

操作系统中的C应用程序在执行时其占用的内存细分如下:

代码区:存放代码
数据区:存放数据 
动态数据区 
堆:动态内存申请区,malloc/free
栈:局部变量区,系统自动申请自动释放
静态数据区:存放全局变量,静态变量,常量,未初始化的静态数据全部初始化为0
裸机中的应用程序
裸机中的应用程序内存分配都是由编译器和链接配置文件指定的,其可能分为若干个段,包括代码区,堆栈区,数据区,常量区等的大小和地址,链接后各变量和代码的详细内存分配可以查看内存的map文件(一般而言都可产生)。且代码区和常量区是放在flash的地址空间!!!

注: 
裸机应用与操作系统应用的区别: 
(1)操作系统上编译连接好的程序(如.exe)存放在磁盘中,执行时首先将代码复制到内存(SDRAM)中,然后由操作系统为该应用开辟一个进程,并分配内存。程序中可使用标准C库malloc等动态分配内存的函数 
(2)裸机上的应用由于没有操作系统的管理,其下载好的代码存放在Flash里,在执行的时候直接从flash里读取命令(没有复制到SDRAM这一步,除了中断向量表等对响应速度要求特别高的代码以外)。常量也是存在flash里。由于无操作系统,故无法在裸机中正常使用malloc函数。若非要使用malloc也可以,不过需要在使用之前先使用stdlib.h中的以下函数指定动态分配空间的内存位置和大小。

void init_mempool (void _MALLOC_MEM_ *p, unsigned int size);//起始地址和大小
1
不过一般不推荐这样使用,因为采用malloc函数动态申请的时候会产生内存碎片,这对于RAM本来就特别稀缺的单片机来说非常不可取!应该是自己写一个动态内存分配的函数!!!
--------------------- 
作者:遍地流金 
来源:CSDN 
原文:https://blog.csdn.net/u012177034/article/details/52299887 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/qq_19004627/article/details/85848634