const 类型限定符

来自cppreference.com
< c‎ | language

C 类型系统中每一个独立的类型在都有数个该类型的限定版本,对应 constvolatile及对于指向对象指针的 restrict 限定符中的一个、两个或全部三个。此页面描述 const 限定符的效果。

编译器可以把声明带 const 限定类型的对象放到只读内存中,而且若程序决不取该 const 对象的地址,则可能完全不存储它。

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

若以 const 类型限定符声明数组类型(通过使用 typedef ),则数组类型无 const 限定,但其元素类型有。若以 const 类型限定符声明函数类型(通过使用 typedef ),则行为未定义。

typedef int A[2][3];
const A a = {{4, 5, 6}, {7, 8, 9}}; // const int 的数组的数组
int* pi = a[0]; // 错误: a[0] 拥有 const int* 类型

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; // OK :添加限定符( int 到 const int )
p = cp; // 错误:舍弃限定符( const int 到 int )
p = (int*)cp; // OK :转型

注意指向指向 T 指针的指针不可转换为指向指向 const T 指针的指针;对于要兼容的二个类型,其限定必须等同。

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

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

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

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

下列二个声明声明同一函数:

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

关键词

const

注意

C 从 C++ 接纳了 const 限定符,但不同于 C++ 中, C 中 const 限定类型的表达式不是常量表达式;它们不可用作 case 标号,或用于初始化静态线程存储期对象、用作枚举项位域大小。以之为数组大小是,产生的数组为 VLA 。

引用

  • C11 standard (ISO/IEC 9899:2011):
  • 6.7.3 Type qualifiers (p: 121-123)
  • C99 standard (ISO/IEC 9899:1999):
  • 6.7.3 Type qualifiers (p: 108-110)
  • C89/C90 standard (ISO/IEC 9899:1990):
  • 3.5.3 Type qualifiers

参阅