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

本文详细介绍了C语言中的存储类别,包括作用域、链接性,如全局变量、静态本地变量、寄存器变量等,并探讨了内存管理的三个方面:自动存储、动态内存分配和静态存储。同时,讲解了const、volatile、restrict和_Atomic等类型限定符的用途,以增强程序的优化和线程安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

存储类别,链接

一些名称

  1. (标识符–名称 左值–指定内存位置的内容)
  2. 存储期描述对象,标识符用于访问对象,可以用作用域和链接描述

关于作用域(易混淆的例子)
注意:有些编译器不支持,需添加声明。

  • while(x++<33) {int x=100 x++;}
    该变量只定义在while循环中,当执行循环体的时候,是新的x被定义为100后递增,每轮迭代结束,新的x变量就消失,进入循环测试条件使用并递增原始的x,再次进入循环,再次创建新的x。若x初始值为30,该循环进入三次,最后输出结果应为34.
    新的x被创建和销毁三次
  • 定义在块内的变量,作用域仅为块内。
    若一个变量名同时定义在开头,循环判断条件,循环中。
    分别为原始的,索引的,循环体内的。
    他作为循环的索引时,隐藏原始的n,后进入循环,新的n隐藏了索引n,结束一轮后,声明在循环体内的n消失,循环头使用索引n进行测试。整个循环结束后,原始的n重新起作用。

全局变量初始化

  • 没有做初始化的全局变量会得到0值
  • 指针会得到NULL值
  • 他们的初始化发生在main以前
  • 只能用编译时刻已知的值来初始化全局变量(变量不行)

被隐藏的全局变量

  • 如果函数内部 存在与全局变量同名的变量,则全局变量被隐藏

静态本地变量(与全局变量放在一起)
特殊(全局生存区,本地作用域)

  1. 在本地变量定义时加上static修饰符就成为静态本地变量
  2. 当函数离开的时候,静态本地变量会继续存在并且保持其值
  3. 静态本地变量的初始化只会在第一次进入这个函数时做,以后进入函数时会保持上次离开的值(若多次调用函数,函数中有定义,该变量下一次进来的值为上次离开后的,不会重新初始化)。

几种变量

  1. 块作用域的静态变量
    static
    静态变量和外部变量在程序被载入内存时已经执行完毕,声明只执行一次,后续反复经过该声明时程序会跳过。
    注意:不能在函数形参中使用,古老书中,这种存储类别被称为内部静态存储类别内部指函数内部,非内部链接。
  2. 寄存器变量
    register声明
    寄存器变量存储在CPU的寄存器中访问处理会快一些但无法获取地址。
    使用时仅只是请求,编译器不一定会实现。但仍然无法获取地址。
  3. 外部链接的静态变量
    该变量具有文件作用域,外部链接和静态存储期属于外部变量,放在所有函数外面(定义式声明:预留空间)。在函数中,可以用
    extern声明,跨文件时必须声明。(引入式声明
  4. 内部链接的静态变量
    该存储类别具有静态存储期,文件作用域,和内部链接。
    在所有函数外部用static定义。只能用于同一个文件的函数。可用extern声明后使用定义在别处的内部链接的静态变量,但并未改变其内部链接属性。

补充:其他存储类别说明符

extern,static,register,auto…

  1. auto 该说明符表明变量是自动存储期,只能用于块作用域变量声明中。由于在块中声明的变量本身就具有自动存储期,所以使用auto主要是为了表明要使用与外部变量同名的局部变量的意图。
  2. typedef与任何内存存储无关,不能使用多个存储类别说明符作为typedef的一部分。
  3. 例外_Thread_local可以和ststic和extern一起用。

内存管理

程序把他可用的内存分为3部分

  • 一部分供具有外部链接,内部链接和无链接的静态变量使用

  • 供自动变量使用

  • 供动态内存分布

  • 自动存储类别的变量 进入变量所在块时存在,程序离开块后消失,这部分内存通常作为栈来处理,新创建的变脸按顺序加入内存,然后以相反顺序进行销毁。

  • 动态内存在调用malloc或相关函数时存在,free()后释放。内存块可以在一个函数中创建,另一个函数中销毁。所以,该部分内存用域动态分配会支离破碎,未使用的内存块分散在已使用的内存块之间。并且,使用动态内存通常比使用栈内存慢。

ANSI C类型限定符

  • const
  1. 以它为关键字生命的对象,其值不能通过赋值或递增递减来修改。
  2. 指针
const float * pf;=float const *pf

*pf指向一个float类型的const的值
pf指向的值不能被改变,而pf本身的值可以改变,可以使指针指向其他const值。

float * const pt;

*pt创建指针pt本身的值不能更改,pt必须指向同一个地址,但是它所指向的值可以改变。

const float * ptr;

ptr既不能指向别处,他所指的值也不能改变
(应用:数组名作为实参传递给函数中,使用const可以不改变数组的值)
例:void display(const int array[],int limit);
(static级const可以放在函数原型和函数头的形式参数的初始方括号中,static新用法:告知编译器如何使用形式参数,目的是让编译器使用这些信息优化函数的编码)

  • volatile类型限定符
  1. 该类型限定符告知计算机,代理(而不是变量所在的程序)可以改变该变量的值。通常被用于硬件地址以及在其他程序或同时运行的线程中共享数据
  2. 语法与const一样
  3. 可以同时使用。通常const把硬件时钟设置为程序不能更改的变量,但是可以通过代理改变。同时使用两个限定符,顺序不重要。
  • restrict类型限定符
  1. 只能用于指针,表明该指针是访问数据对象的唯一且初始的方式,且编译器可以自由假定一些优化方案。
  2. 还可用于函数形参中的指针,编译器可以假定在函数体内其他标识符不会修改该指针指向的数据。
  • _Atomic类型限定符
  1. 管理访问相同数据的不同线程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值