存储类别、链接和内存管理(一)--面试中你遇到过static关键字吗?

简介: 主要介绍作用域,链接,存储期。

   halo大家好~今天我们来分享一下在有关C语言面试中我们最常被面试官问到的static关键字到底有什么用?相信学完本期内容你就会回答了~

一、存储类别

   首先我们来了解下存储类别。

   从硬件方面看,每个变量存储的值都占用一定的物理内存空间,C语言中把这样一块内存称为对象。    

   从软件方面看,程序需要访问对象,可以通过声明变量来完成:

int entity = 3;

   程序通过访问标识符entity去访问对象。

640.png

一般而言,那些指定对象的表达式称为左值,即entity即是标识符也是左值。如果可以使用左值改变对象中的值,该左值就是一个可修改的左值(modifiable value)。很简单吧,如果你理解不了,想象一下,我要将存储3的内存空间改成4怎么做?

entity = 4;

通过标识符entity(左值)去修改某一内存空间的值。

再看一个例子,声明:

const char *pc = “hello world!”;

640.png

字符串“hello world!”存放在一段连续的内存空间里,假设从地址0x56000000开始,那pc存放的值就是0x56000000,即pc的值存放了字符串的地址。

我们可以让pc重新指向其他字符串(改变pc里的值),所以标识符pc是个可修改的左值,const保证了被pc指向的字符串内容不被修改,但是无法保证pc不指向其他字符串。但是*pc不是可修改的左值,因为*pc指定了储存‘h’字符的数据对象。

可以用存储期描述对象,所谓存储期是指对象在内存中保留了多长时间。

标识符用于访问对象,使用作用域和链接描述标识符。

1.1 作用域

   作用域描述程序中可访问标识符的区域。一个C变量的作用域可以是:

块作用域、函数作用域、函数原型作用域或文件作用域。

块就是一对用花括号{}括起来的代码区域,我们使用的局部变量、函数的形参都具有块作用域。C99把块的概念拓展到包括for循环、while循环,例如:

for(int i=0;i<5;i++);

变量i的作用域也是块作用域,一旦循环结束,就不能再访问i。

   函数作用域(function scope)仅用于goto语句的标签。这意味着即使一 个标签首次出现在函数的内层块中,它的作用域也延伸至整个函数。如果在 两个块中使用相同的标签会很混乱,标签的函数作用域防止了这样的事情发 生。

   函数原型作用域的范围是从形参定义处到原型声明结束。这意味着,编 译器在处理函数原型中的形参时只关心它的类型,而形参名(如果有的话) 通常无关紧要。而且,即使有形参名,也不必与函数定义中的形参名相匹 配。只有在变长数组中,形参名才有用。

   变量的定义在函数的外面,具有文件作用域(file scope)。具有文件作 用域的变量,从它的定义处到该定义所在文件的末尾均可见。定义在函数体外,这样的变量可用于多个函数,所以文件作用域变量也称为全局变量(global variable)。

所以,局部变量具有块作用域,全局变量具有文件作用域。

1.2 链接

   说到链接,首先我们要知道C变量具有3种链接属性:外部链接、内部链接和无链接。

C预处理时,用包含的头文件内容替换#include指令,编译器源代码文件和所有的头文件都看成是一个包含信息的单独文件。这个文件被称为翻译单元 (translation unit)。

具有块作用域、函数作用域或函数原型作用域的变量都是无链接变量。

具有文件作用域的变量可以是外部链接或内部链接。

外部链接变量可以在多文件程序中使用,内部链接变量只能在一个翻译单元中使用(即一个源代码文件和它所包含的头文件)。

但是,对程序员而言这些术语太长了。一 些程序员把“内部链接的文件作用域”简称为“文件作用域”,把“外部链接的文件作用域”简称为“全局作用域”或“程序作用域”。

那么如何知道文件作用域是内部链接还是外部链接呢?就看外部定义中有没有static!举个例子:

int i = 6;            //文件作用域,外部链接
    static int k = 6;  //文件作用域,内部链接
    int main(void)
   {
        ...
   }

   该文件和同一程序的其他文件都可以使用变量i。而变量k属文件私有,该文件中的任意函数都可使用它。

总结:当你的Project里有多个C文件的时候,编译器编译它们的时候所有文件都能使用变量i,而加了static的全局变量k,则只有该文件可以使用,其他文件是看不到变量k的。

1.3 存储期

  C对象有4种存储期:静态存储期、线程存储期、自动存储期、动态分配存储期。

静态存储期:如果对象具有静态存储期,那么它在程序的执行期间一直存在。文件作用域变量具有静态存储期。注意:static仅仅是声明了它的链接属性,而无论是外部连接还是内部连接,所有的文件作用域都具有静态存储期。

线程存储期用于并发程序设计,程序执行可被分为多个线程。具有线程 存储期的对象,从被声明时到线程结束一直存在。以关键字_Thread_local声 明一个对象时,每个线程都获得该变量的私有备份。

块作用域的变量通常都具有自动存储期。当程序进入定义这些变量的块时,为这些变量分配内存;当退出这个块时,释放刚才为变量分配的内存。我们到目前为止使用的局部变量都是自动类别。

注意:块作用域变量也能具有静态存储期。为了创建这样的变量,要把变量声明在块中,且在声明前面加上关键字static。

640.jpg

总的来说:static关键字的作用就是限制作用域和存储期。通常面试官还会跟全局变量和局部变量一起问的哦~    

号主:一枚机械专业本科生,经历了转行,从外包逆袭到芯片原厂的Linux驱动开发工程师,深入操作系统的世界,贯彻终身学习、终身成长的理念。平时喜欢折腾,寒冬之下,抱团取暖,期待你来一起探讨技术、搞自媒体副业,程序员接单和投资理财。【对了,不定期送闲置开发板、书籍、键盘等等】。

如果你想了解我的转行经验,欢迎找我交流~gongzhong号【哆哆jarvis】

一起不断探索自我、走出迷茫、找到热爱,希望和你成为朋友,一起成长~


相关文章
|
存储
阿里云轻量应用服务器收费标准价格表:200Mbps带宽、CPU内存及存储配置详解
阿里云香港轻量应用服务器,200Mbps带宽,免备案,支持多IP及国际线路,月租25元起,年付享8.5折优惠,适用于网站、应用等多种场景。
3960 0
|
存储 缓存 NoSQL
内存管理基础:数据结构的存储方式
数据结构在内存中的存储方式主要包括连续存储、链式存储、索引存储和散列存储。连续存储如数组,数据元素按顺序连续存放,访问速度快但扩展性差;链式存储如链表,通过指针连接分散的节点,便于插入删除但访问效率低;索引存储通过索引表提高查找效率,常用于数据库系统;散列存储如哈希表,通过哈希函数实现快速存取,但需处理冲突。不同场景下应根据访问模式、数据规模和操作频率选择合适的存储结构,甚至结合多种方式以达到最优性能。掌握这些存储机制是构建高效程序和理解高级数据结构的基础。
1298 1
|
存储 NoSQL Redis
阿里面试:Redis 为啥那么快?怎么实现的100W并发?说出了6大架构,面试官跪地: 纯内存 + 尖端结构 + 无锁架构 + EDA架构 + 异步日志 + 集群架构
阿里面试:Redis 为啥那么快?怎么实现的100W并发?说出了6大架构,面试官跪地: 纯内存 + 尖端结构 + 无锁架构 + EDA架构 + 异步日志 + 集群架构
阿里面试:Redis 为啥那么快?怎么实现的100W并发?说出了6大架构,面试官跪地: 纯内存 + 尖端结构 +  无锁架构 +  EDA架构  + 异步日志 + 集群架构
|
存储 弹性计算 固态存储
阿里云服务器配置费用整理,支持一万人CPU内存、公网带宽和存储IO性能全解析
要支撑1万人在线流量,需选择阿里云企业级ECS服务器,如通用型g系列、高主频型hf系列或通用算力型u1实例,配置如16核64G及以上,搭配高带宽与SSD/ESSD云盘,费用约数千元每月。
1865 0
|
Java 程序员
面试官的加分题:super关键字全解析,轻松应对!
小米,29岁程序员,通过一个关于Animal和Dog类的故事,详细解析了Java中super关键字的多种用法,包括调用父类构造方法、访问父类成员变量及调用父类方法,帮助读者更好地理解和应用super,应对面试挑战。
369 3
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
1346 1
|
Java 程序员
Java 面试高频考点:static 和 final 深度剖析
本文介绍了 Java 中的 `static` 和 `final` 关键字。`static` 修饰的属性和方法属于类而非对象,所有实例共享;`final` 用于变量、方法和类,确保其不可修改或继承。两者结合可用于定义常量。文章通过具体示例详细解析了它们的用法和应用场景。
551 3