const 类型限定符
C 类型系统 中的每个单独类型都有该类型的几个限定版本,对应于 const
、volatile
和(对于指向对象类型的指针)restrict
限定符中的一个、两个或所有三个。本页介绍了 const
限定符的影响。
使用 const 限定类型 声明 的对象可能会被编译器放置在只读内存中,如果程序中从未获取 const 对象的地址,则它可能根本不会被存储。
任何试图修改类型为 const 限定类型的对象都会导致未定义的行为。
const int n = 1; // object of const-qualified type int* p = (int*)&n; *p = 2; // undefined behavior
const
语义仅适用于 左值 表达式;当 const 左值表达式在不需要左值的上下文中使用时,它的 const
限定符会丢失(注意,如果存在 volatile 限定符,则不会丢失)。
指定 const 限定类型对象的左值表达式和指定结构体或联合体类型对象的左值表达式(其中至少有一个成员的类型为 const 限定类型(包括递归包含的聚合体或联合体的成员))不是可修改左值。特别是,它们不可赋值。
const int n = 1; // object of const type n = 2; // error: the type of n is const-qualified int x = 2; // object of unqualified type const int* p = &x; *p = 3; // error: the type of the lvalue *p is const-qualified struct {int a; const int b; } s1 = {.b=1}, s2 = {.b=2}; s1 = s2; // error: the type of s1 is unqualified, but it has a const member
const 限定结构体或联合体类型的成员会获取其所属类型的限定符(使用 .
运算符或 ->
运算符访问时)。
struct s { int i; const int ci; } s; // the type of s.i is int, the type of s.ci is const int const struct s cs; // the types of cs.i and cs.ci are both const int
如果数组类型使用 const 类型限定符声明(通过使用 typedef),则数组类型不是 const 限定的,但其元素类型是。 |
(直到 C23) |
数组类型及其元素类型始终被认为是相同 const 限定的。 |
(自 C23 起) |
typedef int A[2][3]; const A a = {{4, 5, 6}, {7, 8, 9}}; // array of array of const int int* pi = a[0]; // Error: a[0] has type const int* void *unqual_ptr = a; // OK until C23; error since C23 // Notes: clang applies the rule in C++/C23 even in C89-C17 modes
如果函数类型使用 const 类型限定符声明(通过使用 typedef),则行为未定义。
在函数声明中,关键字 以下两个声明声明了相同的函数 void f(double x[const], const double y[const]); void f(double * const x, const double * const y); |
(自 C99 起) |
const 限定的复合字面量不一定指定不同的对象;它们可能会与其他复合字面量和恰好具有相同或重叠表示形式的字符串字面量共享存储空间。 const int* p1 = (const int[]){1, 2, 3}; const int* p2 = (const int[]){2, 3, 4}; // the value of p2 may equal p1+1 _Bool b = "foobar" + 3 == (const char[]){"bar"}; // the value of b may be 1 |
(自 C99 起) |
指向非 const 类型的指针可以隐式转换为指向相同或 兼容 类型的 const 限定版本的指针。反向转换需要强制转换表达式。
int* p = 0; const int* cp = p; // OK: adds qualifiers (int to const int) p = cp; // Error: discards qualifiers (const int to int) p = (int*)cp; // OK: cast
请注意,指向指向 T
的指针不是可转换为指向指向 const T
的指针的;对于两个类型要兼容,它们的限定符必须相同。
char *p = 0; const char **cpp = &p; // Error: char* and const char* are not compatible types char * const *pcp = &p; // OK, adds qualifiers (char* to char*const)
内容 |
[编辑] 关键字
[编辑] 注释
C 从 C++ 中采用了 const 限定符,但与 C++ 不同,C 中的 const 限定类型表达式不是 常量表达式;它们不能用作 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 类型限定符 (p: 108-110)
- C89/C90 标准 (ISO/IEC 9899:1990)
- 6.5.3 类型限定符
[编辑] 另请参阅
C++ 文档 的 cv(
const 和 volatile )类型限定符 |