C
Compiler support
Language
Headers
Type support
Program utilities
Variadic function support
Error handling
Dynamic memory management
Strings library
Algorithms
Numerics
Date and time utilities
Input/output support
Localization support
Concurrency support
(C11)
Technical Specifications
Symbol index
C language
Basic concepts
Keywords
Preprocessor
Statements
Expressions
Initialization
Declarations
Functions
Miscellaneous
History of C
Technical Specifications
Declarations
Pointer
Array
enum
struct
union
Bit-field
Atomic types
(C11)
const
constexpr
(C23)
volatile
restrict
(C99)
Alignment specifiers
Storage duration and linkage
External and tentative definitions
typedef
Static assertions
Attributes
(C23)
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)
目录
1
关键字
2
注释
3
参考文献
4
另请参阅
关键词
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
)类型限定符