C语言之存储类型及内存管理

一. 存储类

一个变量在程序中的存在一般可以从时间和空间两个角度去描述。
时间就是变量在内存中存活的时间即存储时期。空间可以从变量的作用域和链接属性去描述。

1.作用域

C变量的作用域分为代码块作用域,函数原型作用域,文件作用域3种。
代码块作用域:从该变量被定义的地方到包含该定义的代码块的末尾该变量均可见。比如函数,复合语句
函数原型作用域:从变量定义处一直到原型声明的末尾。在该作用域中,编译器只关心参数类型,但是变长数组除外。

void test(int n,int m,char A[n][m])

文件作用域:在所有函数之外定义的变量具有文件作用域,具有文件作用域的变量从定义处到文件结尾处都是可见的。

2.链接

C语言的链接分为外部链接,内部链接,空链接。
空链接:具有代码块作用域和函数原型作用域的变量有空链接,即该变量被代码块和函数原型私有。
外部链接:具有文件作用域的非static变量有外部链接,可以在多文件的任何地方使用。
内部链接:具有文件作用域的static变量有内部链接,可以在该变量所在文件的任何地方使用。
具有文件作用域的变量,static表示链接属性
具有代码块作用域的变量,static表示存储时期

3.存储时期

C语言变量有两种存储时期,静态存储时期和自动存储时期。
静态存储时期:程序执行期间一直存在,即变量所占内存一经分配一直存在
自动存储时期:使用时分配内存,不使用释放内存

具有文件作用域的变量都具有静态存储时期。
具有代码块作用域的静态变量具有静态存储器。

在这里插入图片描述

4.存储类

auto 自动变量

在代码块和函数实参里定义的非static变量都是自动变量。自动变量具有自动存储时期,代码块作用域,空链接。

自动变量也就是局部变量,未初始化的情况下,该变量的初值是先前占用分配给它的空间的任意值,不一定是0。

例如:存在局部变量A和B,A在B执行之前释放内存,如果B没有初始化且B被分配的内存恰巧就是之前A所占的内存,那么B的初值可能是A的值,也可能是其他值,由编译器决定。换句话说就是B的初值不可预知。

嵌入式中的寄存器配置异常一般都是这个问题,寄存器相关变量一定要初始化。
切记!切记!切记!

全局变量不初始化的话默认为0,但是初始化,不初始化差别很大。全局变量初始化的,编译器标记为强符号,未初始化标记位弱符号。

如果有多个重名强符号报错。

如果有一个强符号,多个弱符号,以强符号为准。

如果为多个重名弱符号,任选一个。

register 寄存器变量

寄存器变量是存放在CPU的寄存器中的,一般变量都是存放在内存中的。

放在寄存器中的变量有两个特点:一个是运算速度快,一个是不能取地址。
不同的CPU对寄存器变量的数目和类型的限制是不同的,并不是所有类型的变量都可以定义为寄存器变量。寄存器变量一般是使用频繁的变量。

代码块作用域的静态变量

静态变量是指变量的位置固定不变,具有文件作用域(全局)的变量自动具有静态存储时期。

具有代码块作用域(局部)的静态变量在函数完成处理后变量并不消失,从这次函数调用到下一次函数调用,内存都记录着它们的值,直到整个程序结束。

外部链接(全局)的静态变量

具有外部链接的静态变量具有文件作用域,外部链接,静态存储期。这一类型变量被称为外部变量。如果变量在别的文件定义,在另一个文件使用该变量用extern声明是必须的。

定义声明和引用声明:
定义声明:定义声明是指该变量(具有文件作用域,外部链接)之前未曾定义进行首次定义,变量 tern 为定义声明。

int tern; //定义声明
test()
{ }

引用声明:引用声明是告诉编译器该变量在之前的某个地方定义过,不需要重新定义,是需要引用而已。

/*文件A*/
int tern; //定义声明

/*文件B/
extern int tern; //引用声明

内部链接的静态变量

内部链接的静态变量具有文件作用域,静态存储期,内部链接。该变量通过static修饰符在所有函数外部定义。该变量只能被该文件内的函数使用。

5.存储类说明符

说明符作用
auto显示的表明变量具有自动存储时期,只用在代码块作用域中
register只能用于具有代码块作用域的变量,将变量存储在寄存器中,方便快速的读取
static用于具有代码块作用域的变量,使变量具有静态存储时期;用于具有文件作用域的变量,使变量具有内部链接
extern声明一个已经在别处定义的变量

二.内存分配

1.内存区

在这里插入图片描述
栈区
编译器自动分配释放,存储的是函数形参,局部变量等

堆区
由程序员分配释放
堆和栈的区别:由系统自动分配释放,堆由程序员自动分配释放。C中由函数malloc分配,free释放。C++中由new分配,delete释放。

全局区
由编译器分配,直到程序运行结束释放。存储的是全局变量和静态变量。
初始化的全局变量和静态变量放在data段,未初始化的全局变量放在bss段。
全局变量也可由程序员指定地址 attribute()
https://blog.youkuaiyun.com/qlexcel/article/details/92656797.

文字常量区
常量数据存储位置

程序代码区
代码存储位置

2.malloc( )和free( )

C中堆区的分配使用malloc函数,释放使用free函数。
malloc()的参数是内存字节数,调用malloc可以在内存中找到一块大小合适的块,返回的是内存第一个字节的地址,可以将返回值赋值给指针变量。如果内存中没有足够的空间则malloc返回空指针。

每次malloc一块内存,使用结束后都要free。free()的参数是动态分配的内存的首地址。

double* ptd; //定义一个double类型的指针
ptd=(double*)malloc(10*sizeof(double)); //分配10个double大小的内存区,malloc的返回值强制转换为double类型的指针
free(ptd);//释放内存
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值