名稱空間
變體
操作

const 型別限定符

來自 cppreference.com
< c‎ | 語言

C 型別系統 中的每個單獨型別都有其幾種限定版本,對應於 constvolatile,以及(對於指向物件型別的指標)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

如果一個數組型別透過使用 typedef 宣告為 const 型別限定符,則該陣列型別本身不是 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

如果一個函式型別透過使用 typedef 宣告為 const 型別限定符,則行為是未定義的。

在函式宣告中,關鍵字 const 可以出現在用於宣告函式引數的陣列型別的方括號內。它限定了陣列型別轉換成的指標型別。

以下兩個宣告聲明瞭相同的函式。

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)

目錄

[編輯] 關鍵字

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(constvolatile)型別限定符