前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浅谈一下存储类别

浅谈一下存储类别

原创
作者头像
九问
修改2021-09-19 20:26:21
4760
修改2021-09-19 20:26:21
举报
文章被收录于专栏:C语言学习

C语言中存储类别也就是storage class,它的定义是在一个C程序里面变量variables和函数functions的可见作用域(visible scope)和生命周期(life-time),我们有5种存储类别:

存储类别

存储期

作用域

链接

声明方式

自动

自动

块内

寄存器

自动

块内,使用关键字register

静态外部链接

静态

文件

外部

所有函数外

静态内部链接

静态

文件

内部

所有函数外,使用关键字static

静态无链接

静态

块内,使用关键字static

接下来我就翻译翻译上面的一些概念,以及我自己的理解方式

存储类别是提供给我们在内存中存放数据的,它的基本单位是块,我们把这样一块内存成为对象(object),object是存放数据的memory location, object相当于一间房,我们在房间里可以放一个物品,也可以放多个物品,前提是不要满了,因为硬件上给的内存是有限的,当然我们也可以不放。object作为memory location是不变的,但是存储的数据是可以变的,比如对于自动变量,它没用前不占用,用完后变量消失,也不占用。然后咱们再来说说变量variables,程序需要一种方法来访问咱们的object,比入

代码语言:txt
复制
char *pt = "something";
int str = 5;

在这个例子里,pt便是指向对象的,对象是"something",这是一个内存地址,我们使用了指针来指向object,我们也可以使用(pt+2)来指向字符'm'的地址,他是一个可以改变的左值,str是标识符identifier,那么他是用来指向特定对象的内容,在这里对象就是&str,内容是5。

那么标识符可以访问对象,那么我们使用作用域scope和链接linkage来描述它

##什么叫做作用域

作用域就是一个变量的作用范围,比如

代码语言:txt
复制
int global = 4;    //全局变量,整个程序都可见
int keng(int pt)   //pt作用域开始
{     
    int i;
    for(i=0;i<10;i++)     
    {
        int p=0;      //p作用域开始
        global+=pt+p;
    }                    //p作用域结束
    return global;
}                   //pt作用域结束

显然p是块作用域,它只在定义p后的for循环块里是有效的,而pt是函数作用域,他在函数keng里面是有效的,出了函数就不可见了。而变量global是文件作用域,它在整个文件中是可见的,包括下面的所有函数,我们也通常称之为全局变量(global variable)

何为链接

linkage在维基百科中是这样定义的

linkage describes how names can or can not refer to the same entity throughout the whole program or one single translation unit.

也就是链接描述了变量名是否能通过整个程序或者翻译单元来指向相同的对象。通俗点就是我定义了一个变量名,然后我其他地方也有相同的变量名,两个变量名是否指向同一个位置,我的地址是否是一样的。C变量有三种链接属性:外部链接,内部链接以及无链接。具有块作用域、函数(原型)作用域的变量都是无链接属性,属于这些定义他们的块、函数所私有,出了这个界,哪怕是相同名字的变量,那意义也不同了。外部链接变量可以在多文件程序中使用,而内部链接只能在一个翻译单元(一个源代码文件和它所包含的.h头文件)使用。区分外部链接和内部链接的方式是内部链接使用关键字static,默认是外部链接。

存储期的概念

存储期是描述通过标识符访问的对象的生命期,而生命期是指为变量或者函数从分配内存到释放的内存的一个持续时间,C一共有4种存储期:静态存储期、线程存储期、自动存储期、动态分配存储期。

  • 静态存储期:如果对象具有静态存储期,则它在程序执行期间一直都存在,前面所提到的文件作用域就有静态存储期。
代码语言:txt
复制
void function[int number]
{
    static int m = 0;  //块作用域,但是静态存储期,无链接
    number+= m;       //number是块作用域,但是自动存储期,无链接
    m++;
}

特别注意的是块存储里的用static关键字的变量是在程序进入内存就已执行完毕,不是到了函数这里才执行,遇到它函数会选择跳过。举个例子:

代码语言:txt
复制
#include <stdio.h>
void est(void);
int main()
{
	int number;
	for (number = 0; number < 4; number++)
	{
		est();
	}
}
void est(void)
{
	int n = 0;
	static int m = 0;
	printf("n=%d,m=%d\n",n++,m++);
}

执行代码后结果为:

static.png
static.png

因为n是自动存储变量,每次循环都会执行n=0的语句,所以n始终为0,而m是静态变量,m只在程序载入内存时执行,在函数里是不会再次执行的。

  • 线程存储期:线程存储期用于并发程序设计,程序执行可以被分为多个线程。那么我先翻译一下什么叫做线程。线程在维基百科中是这样定义的:线程(英语:thread)是操作系统能够进行运算调度的最小单位。大部分情况下,它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并行多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。一个进程有许多线程,使用多线程的好处就是各干各的事,类似于一只手完成任务变成多只手一起完成,从而大大提高了工作效率。线程存储期每个线程都有该对象对应的实例。
  • 自动存储期:程序不进入时不分配内存,进入定义这些变量的块后开始分配内存,离开块后释放内存,相当于我们计算时用到可擦写草稿纸,我要计算一个结果,可能中间要用到其他变量,但是最终我只要得到结果的全局变量,其他变量计算完就可以擦掉了,当进行另外计算时这个“可擦写草稿纸”即内存又可以给其他变量使用。块作用域变量通常都有自动存储期,当然,块作用域也可以拥有静态存储期。

对于内部链接我们一般用static,对于外部链接,你可以不用关键字,用关键字其实目的是提醒读者这是一个外部链接变量,通常当我们读到多个源文件时,外部变量只声明一次,在其他地方,一般会用关键字extern,提醒你这个变量是整个程序共用的。对于寄存器变量,我们使用关键字register,如果寄存器愿意的话(因为寄存器存储空间有限,你的大小要是很大寄存器会有可能拒绝)。这样做的好处是你的变量处理会很快,缺点是无法获得这个变量的地址,如果你用函数想返回这个值到主函数是不可能的,因为指针没用了。

总的来说,存储类别搞清楚作用域、存储期、链接以及它们的四个声明方式,就能很好的区分了。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 接下来我就翻译翻译上面的一些概念,以及我自己的理解方式
    • 何为链接
      • 存储期的概念
      相关产品与服务
      对象存储
      对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档