类型限定符
类型限定符为标识符提供两个属性之一。 const
类型限定符将对象声明为不可修改。 volatile
类型限定符声明一个项,该项的值可由超出该项所在的程序控制范围的某个项(如并发执行的线程)合理更改。
const
、restrict
和 volatile
这几个类型限定符只能在声明中出现一次。 类型限定符可与任何类型说明符一起出现;但是,它们不能在多项声明中的第一个逗号的后面出现。 例如,以下声明是合法的:
typedef volatile int VI;
const int ci;
以下声明是非法的:
typedef int *i, volatile *vi;
float f, const cf;
仅当访问作为表达式的左值的标识符时,类型限定符才会相关。 有关左值和表达式的信息,请参阅左值表达式和右值表达式。
语法
type-qualifier
:
const
restrict
volatile
const
和 volatile
以下是合法的 const
和 volatile
声明:
int const *p_ci; // Pointer to constant int
int const (*p_ci); // Pointer to constant int
int *const cp_i; // Constant pointer to int
int (*const cp_i); // Constant pointer to int
int volatile vint; // Volatile integer
如果数组类型的规范包括类型限定符,则将限定元素而不是数组类型。 如果函数类型的规范包括限定符,则行为是不确定的。 volatile
和 const
都不会影响值的范围或对象的算术属性。
const
关键字可用于修改任何基本或聚合类型,或修改指向任何类型的对象的指针或typedef
。 如果某项声明为只包含const
类型限定符,则其类型被视为 const int。可以初始化const
变量,也可以将该变量置于存储的只读区域中。const
关键字对于声明指向const
的指针很有用,因为这要求函数不以任何方式更改指针。编译器假定可通过使用或修改
volatile
变量的值未知过程来访问该变量(在程序中的任意未知)。 无论在命令行上指定了哪些优化,都必须为volatile
变量的每次赋值或引用生成代码,即使它看起来没有任何效果。
如果单独使用 volatile
,则假定 int
。 volatile
类型说明符可用于提供对特定内存位置的可靠访问。 将 volatile
用于数据对象,这些对象可通过信号处理程序、并行执行程序或特定硬件(如内存映射的 I/O 控制寄存器)访问或更改。 可以为变量的生存期将变量声明为 volatile
,也可以将单个引用强制转换为 volatile
。
- 一个项可以同时是
const
和volatile
,在这种情况下,此项不能被它自己的程序以合法方式修改,但能被一些异步进程修改。
restrict
C99 中引入的 restrict
类型限定符(以 /std:c11
或 /std:c17
模式提供)可应用于指针声明。 它限定指针,而不是它指向的内容。
restrict
是编译器的优化提示,当前作用域中没有其他指针引用相同的内存位置。 也就是说,只使用指针或从其派生的值(例如指针 + 1)在指针的生存期内访问对象。 这有助于编译器生成更多的优化代码。 C++ 具有等效机制 __restrict
请注意,restrict
是你与编译器之间的协定。 如果你对标记为 restrict
的指针使用了别名,则结果是不确定的。
下面是使用 restrict
的示例:
void test(int* restrict first, int* restrict second, int* val)
{
*first += *val;
*second += *val;
}
int main()
{
int i = 1, j = 2, k = 3;
test(&i, &j, &k);
return 0;
}
// Marking union members restrict tells the compiler that
// only z.x or z.y will be accessed in any scope, which allows
// the compiler to optimize access to the members.
union z
{
int* restrict x;
double* restrict y;
};