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
标签或初始化 static
和 thread
存储期对象、枚举器或位域大小。当它们用作数组大小时,生成的数组是 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 类型限定符