Namespaces
Variants

const type qualifier

From zh.cppreference.net

C语言 类型系统 中的每个独立类型都有若干该类型的 限定 版本,分别对应 const 、 volatile 以及(对于对象类型指针) restrict 限定符中的一种、两种或全部三种组合。本页描述 const 限定符的作用效果。

使用 const 限定类型 声明 的对象可能被编译器放置在只读存储器中,如果程序中从未获取 const 对象的地址,则该对象可能完全不被存储。

任何尝试修改被 const 限定类型对象的行为都将导致未定义行为。

const int n = 1; // const限定类型的对象
int* p = (int*)&n;
*p = 2; // 未定义行为

const 语义仅适用于 左值 表达式;当 const 左值表达式在不需要左值的上下文中使用时,其 const 限定符会丢失(注意:如果存在 volatile 限定符,则不会丢失)。

那些指代const限定类型对象的左值表达式,以及那些指代至少包含一个const限定类型成员(包括递归包含的聚合体或联合体成员)的结构体或联合体类型对象的左值表达式,均不属于 可修改左值 。特别需要注意的是,这些表达式不可被赋值:

const int n = 1; // const 类型对象
n = 2; // 错误:n 的类型具有 const 限定
int x = 2; // 非限定类型对象
const int* p = &x;
*p = 3; // 错误:左值 *p 的类型具有 const 限定
struct {int a; const int b; } s1 = {.b=1}, s2 = {.b=2};
s1 = s2; // 错误:s1 的类型为非限定,但包含 const 成员

作为 const 限定结构体或联合体类型的成员,将继承其所属类型的限定条件(无论通过 . 运算符还是 -> 运算符访问时均适用)。

struct s { int i; const int ci; } s;
// s.i 的类型是 int,s.ci 的类型是 const int
const struct s cs;
// cs.i 和 cs.ci 的类型都是 const int

如果数组类型通过使用 typedef 声明了 const 类型限定符,则该数组类型本身不具有 const 限定,但其元素类型具有 const 限定。

(C23 前)

数组类型与其元素类型始终被视为具有相同的 const 限定。

(C23 起)
typedef int A[2][3];
const A a = {{4, 5, 6}, {7, 8, 9}}; // 由常量整数数组构成的数组
int* pi = a[0]; // 错误:a[0] 的类型为 const int*
void *unqual_ptr = a; // C23 前有效;C23 起报错
// 注意:clang 即使在 C89-C17 模式下也遵循 C++/C23 的规则

如果函数类型通过使用 typedef 被声明为带有 const 类型限定符,则其行为是未定义的。

在函数声明中,关键字 const 可以出现在用于声明函数参数数组类型的方括号内。它限定数组类型转换后的指针类型。

以下两个声明声明了相同的函数:

void f(double x[const], const double y[const]);
void f(double * const x, const double * const y);
(since C99)

经 const 限定的复合字面量不一定表示独立的对象;它们可能与其他复合字面量以及恰好具有相同或重叠表示的字符串字面量共享存储空间。

const int* p1 = (const int[]){1, 2, 3};
const int* p2 = (const int[]){2, 3, 4}; // p2 的值可能等于 p1+1
_Bool b = "foobar" + 3 == (const char[]){"bar"}; // b 的值可能为 1
(C99 起)

指向非 const 类型的指针可以隐式转换为指向相同或 兼容类型 的 const 限定版本的指针。反向转换需要显式类型转换。

int* p = 0;
const int* cp = p; // 正确:添加限定符(int 到 const int)
p = cp; // 错误:丢弃限定符(const int 到 int)
p = (int*)cp; // 正确:强制类型转换

注意指向 T 的指针不能转换为指向 const T 的指针;要使两种类型兼容,它们的限定符必须完全相同。

char *p = 0;
const char **cpp = &p; // 错误:char* 与 const char* 不是兼容类型
char * const *pcp = &p; // 正确,添加限定符(从 char* 到 char* const)

目录

关键词

const

注释

C语言从C++引入了 const 限定符,但与C++不同,在C语言中具有const限定类型的表达式不是 常量表达式 ;它们不能用作 switch语句 的case标签,也不能用于初始化 静态存储期 对象、 线程存储期 对象、 枚举成员 或 位域 大小。当它们被用作 数组 大小时,生成的数组是可变长度数组(VLA)。

参考文献

  • C17 标准 (ISO/IEC 9899:2018):
  • 6.7.3 类型限定符 (p: 87-90)
  • C11 标准 (ISO/IEC 9899:2011):
  • 6.7.3 类型限定符 (p: 121-123)
  • C99标准(ISO/IEC 9899:1999):
  • 6.7.3 类型限定符(第108-110页)
  • C89/C90 标准 (ISO/IEC 9899:1990):
  • 6.5.3 类型限定符

参见

C++ 文档 关于 cv( const 与 volatile )类型限定符