代码编织梦想

储存类别,链接和内存管理总结

  一. 内存用于储存程序中的数据,由储存期,作用域和链接表征。
 (一).储存期可以用来描述对象,所谓储存期是指对象在内存中保留了多长时间。不同的存储类别具有不同的储存期,作用域和链接。c对象有四种储存期:静态储存期,线程储存期,自动储存期,动态分配储存期。
1>.静态储存期:在程序执行期间一直存在。文件作用域变量具有静态储存期,对于其而言关键字static表明了其链接属性,而非储存期。以static声明的文件作用域变量具有内部链接。但无论内部链接还是外部链接,所有文件作用域变量都具有静态储存期。
2>.线程储存期:用于并发程序设计,具有线程储存期的对象,从被声明时到线程结束一直存在。
3>.自动储存期:块作用域的变量通常具有自动储存期。当定义时分配内存,退出时释放内存。相当于把自动变量占用的内存视为一个可重复使用的工作区或暂存区。
4>.动态分配存储期:在调用 malloc()(或相关函数)时分配内存,在调用 free() 函数时释放内存
( malloc()函数返回一个指向指定字节数内存块的指针。这块内存被 free() 函数释放便可重复使用,free() 函数以该内存块的地址作为参数。)
 (二).作用域:作用域描述程序中可访问标识符的区域,一个c变量的作用域可以是块作用域,函数作用域,函数原型作用域或文件
1>.块作用域:
所谓块是指:用一对花括号括起来的代码区域。定义在块中的变量具有块作用域,块作用域变量的可见范围是从定义处到包含改定义的块的末尾。
2>.函数作用域:仅用于goto语句标签。即使一个标签首次出现在函数的内块层中,他的作用域也延伸至整个函数。如果在两个块中使用相同的标签会很混乱,标签的函数作用域防止了这样的事情发生。
3>.函数原型作用域:用于函数原型中的形参名,其作用域从形参定义处到原型声明结束,意味着编译器在处理函数原型中的形参时只关心的他类型,而形参名通常无关紧要。就算有形参名,也不必与函数定义中的形参名相匹配。
4>.文件作用域:定义在函数的外面的变量具有文件作用域,从其定义处到该定义所在的文件末尾均可见。
 (三).链接:
c变量中有三种链接属性:外部链接,内部链接和无链接。
无链接变量:具有块作用域,函数作用域或函数原型作用域的变量都是无链接的变量。也就意味着这些变量属于定义他们的块,函数或原型私有。外部链接变量可以在多文件程序中使用,内部链接变量只能在一个翻译单元中使用。而具有文件作用域的变量可以是外部链接或者内部链接。
  二.储存类别
分类:自动、寄存器、静态块作用域、静态外部链接、静态内部链接。
1>.自动 —— 在块中不带存储类别说明符或带 auto 存储类别说明符声明的变量(或作为函数头中的形参)属于自动存储类别,具有自动存储期、块作用域、无链接。如果未初始化自动变量,它的值是未定义的。
2>.寄存器 —— 在块中带 register 存储类别说明符声明的变量(或作为函数头中的形参)属于寄存器存储类别,具有自动存储期、块作用域、无链接,且无法获取其他地址。把一个变量声明为寄存器变量即请求编译器将其储存到访问速度最快的区域。如果未初始化寄存器变量,它的值是未定义的。
3>.静态、无链接 —— 在块中带 static 存储类别说明符声明的变量属于 “静态、无链接” 存储类别,具有静态存储期、块作用域、无链接。只在编译时被初始化一次。如果未显示初始化,它的字节都被设置为 0。
4>.静态、外部链接 —— 在所有函数外部且没有使用 static 存储类别说明符声明的变量属于 “静态、外部链接” 存储类别,具有静态存储期、文件作用域、外部链接。只能在编译器被初始化一次。如果未显示初始化,它的字节都被设置为 0。
5>.静态、内部链接 —— 在所有函数外部且使用了 static 存储类别说明符声明的变量属于 “静态、内部链接” 存储类别,具有静态存储期、文件作用域、内部链接。只能在编译器被初始化一次。如果未显示初始化,它的字节都被设置为 0。
  三.类型限定符
 包括 const、volatile、restrict 和 _Atomic。
1>.const 限定符限定数据在程序运行时不能改变。对指针使用 const 时,可限定指针本身不能改变或指针指向的数据不能改变,这取决于 const 在指针声明中的位置。
2>.volatile 限定符表明,限定的数据除了当前程序修改外还可以被其他进程修改。该限定符的目的是警告编译器不要进行假定的优化。
3>.restrict 限定符也是为了方便编译器设置优化方案。restrict 限定的指针是访问它所指向数据的唯一途径。
4>._Atomic 类型限定符(C11)
并发程序设计把程序执行分成可以同时执行的多个线程。C11 通过包含可选的头文件 stdatomic.h 和 threads.h 提供了一些可选的(不是必须实现的)管理方法。但要通过各种宏函数来访问原子类型。当一个线程对一个原子类型的对象执行原子操作时,其他线程不能访问该对象。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接: https://blog.csdn.net/weixin_52620731/article/details/111131090