C语言存储类修饰符和类型限定符


声明:本文转载自https://my.oschina.net/u/943779/blog/3053391,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

存储类修饰符

声明中出现的存储类修饰符(storage class specifier)用于修改标识符的链接和对应对象的存储周期(链接与存储周期的概念将会在本章后面介绍)。链接(linkage)和存储周期(storage duration)是C语言中常会遇到的困扰。链接(标识符的属性)和存储周期(对象的属性)两者在声明中都会受相同关键字集(存储类修饰符)的影响。本章后面会介绍对象的存储周期可以是动态的、静态的,或已分配的(allocated),而标识符的链接可以是外部(external)、内部(internal)或不作限定的。类似“静态链接”或“外部存储”等说法在C语言中是没有意义的。注意:对象有存储周期,而非链接;标识符有链接,而非存储周期。
一个声明中不能出现多个存储类修饰符。函数标识符只可以使用存储类修饰符extern或static。函数参数只可以使用存储类修饰符register。5种存储类修饰符的含义如下:
auto
声明中有修饰符auto的对象,具有动态存储周期。这种修饰符只能用于函数内的对象声明。在ANSI C中,默认情况下函数内的对象声明都有动态的存储周期,所以不需要使用修饰符auto。
register
当声明对象有动态存储周期时,可以使用修饰符register。该关键字告诉编译器,所声明对象的访问应该尽量快——理想情况下,应该将该对象存储在CPU寄存器(register)中。然而,编译器可能并不会按照理想情况那样做,而是会把用register声明的对象当成普通的动态存储周期对象。不管怎样,只要采用修饰符re-gister声明了对象,就不能用地址运算符对该对象进行操作。
static
被声明为static的函数标识符具有内部链接,换句话说,别的翻译单元无法使用所声明的函数标识符来访问该函数。
被声明为static的对象标识符可能为外部链接,也可能为内部链接,至于是哪一种链接形式,取决于对象的定义是在函数内还是函数外。被声明为static的对象具有静态存储周期。因此,修饰符static允许定义局部对象(也就是具有语句块作用域的对象)为具有静态的存储周期。
extern
被声明为extern的函数和对象标识符具有外部链接。可以在程序中任何地方使用这些标识符。外部对象具有静态的存储周期。
_Thread_local
修饰符_Thread_local声明对象为线程局部(thread-local),表示每个线程都分别具有该对象的实例。只有对象能被声明为线程局部,而函数不能。如果在函数内部声明一个线程局部对象,声明必须具有修饰符extern或static。在一个表达式中,线程局部对象的标识符引用当前线程中对象的本地实例,当前线程指当前计算该表达式的线程。示例请参见14.4.1节。

类型限定符

可以利用类型限定符修改声明中的类型,类型限定符有const、volatile、restrict和_Atomic。声明中可使用多个类型限定符,它们的顺序没有限制。类型限定符列表内可以多次出现相同的类型限定符,或者通过限定typedef名称的方式,反复使用同一个限定符。编译器会忽略重复出现的限定符,将它们视为只出现一次。
各种类型限定符的含义如下:
const
对象的类型如果采用了限定符const,则该对象就是常量。在定义该对象之后,程序无法修改它。
volatile
对象的类型如果采用了限定符volatile,则该对象可以被其他进程或事件修改。关键字volatile告诉编译器在每次使用该对象值时,都要重新读取它,即便程序本身自上一次获取后再没有修改过它的值。这种限定符通常用于硬件接口编程,以防止变量值被外部事件修改后,未能及时更新。
restrict
限定符restrict只适用于对象指针类型。这种类型限定符是C99新增加的,用来告诉编译器,一个被指针所引用的对象,如果它可以被修改,那么只能被restrict限定的指针修改,不能被除该指针以外的其他任何方式修改,无论是直接方式还是间接方式。该特性允许编译器采用特定优化技术,而该技术可能需要restrict特性的支撑。编译器也有可能会忽略限定符restrict,而不对程序结果造成任何影响。
_Atomic
采用类型限定符_Atomic声明的对象是一个原子对象(atomic object)。数组不能是原子对象。对原子对象的支持是可选的:C11实现版本中,如果定义了宏_STDC_NO_ATOMICS_,则表示程序不能声明原子对象。关于原子对象的详细介绍,请参见第14章。
编译器也可以将const对象存储在内存中的只读区域,但是volatile对象不能。如果程序不使用volatile对象的地址,也有可能编译器干脆不为该对象分配内存。
对象如果同时使用了限定符const和volatile,如下例中ticks对象所示,它不能被程序本身修改,但可以被其他事件修改,例如时钟芯片的中断处理程序:
extern const volatile int ticks;

本文发表于2019年05月23日 23:00
(c)注:本文转载自https://my.oschina.net/u/943779/blog/3053391,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1701 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1