const type qualifier
C言語の
型システム
における各々の型には、その型のいくつかの
修飾版
が存在し、
const
、
volatile
、およびオブジェクト型へのポインタについては
restrict
修飾子のうち、1つ、2つ、またはすべての3つの組み合わせに対応します。このページでは
const
修飾子の効果について説明します。
const修飾型で宣言された オブジェクトは、コンパイラによって読み取り専用メモリに配置される可能性があります。また、constオブジェクトのアドレスがプログラム内で決して取得されない場合、そのオブジェクトは全く格納されない可能性があります。
const修飾された型のオブジェクトを変更しようとする試みはすべて未定義動作を引き起こします。
const int n = 1; // const修飾型のオブジェクト int* p = (int*)&n; *p = 2; // 未定義動作
const
のセマンティクスは
lvalue
式にのみ適用される。const lvalue式がlvalueを必要としない文脈で使用される場合、その
const
修飾子は失われる(volatile修飾子が存在する場合、それは失われないことに注意)。
const修飾型のオブジェクトを指定する左辺値式、およびconst修飾型のメンバー(再帰的に含まれる集約型や共用体のメンバーを含む)を少なくとも1つ持つ構造体型または共用体型のオブジェクトを指定する左辺値式は、 変更可能な左辺値 ではありません。特に、これらは代入できません:
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修飾される。 |
(until C23) |
|
配列型とその要素型は常に同一のconst修飾を持つものと見なされる。 |
(since C23) |
typedef int A[2][3]; const A a = {{4, 5, 6}, {7, 8, 9}}; // const intの配列の配列 int* pi = a[0]; // エラー: a[0]はconst int*型 void *unqual_ptr = a; // C23まではOK; C23以降はエラー // 注記: clangはC89-C17モードでもC++/C23のルールを適用する
関数型がconst型修飾子( typedef の使用による)で宣言された場合、動作は未定義です。
|
関数宣言において、キーワード
以下の2つの宣言は同じ関数を宣言します: 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: 修飾子を追加 (int から const int) p = cp; // エラー: 修飾子を破棄 (const int から int) p = (int*)cp; // OK: キャスト
T
へのポインターから
const T
へのポインターへは変換できないことに注意してください。2つの型が互換性を持つためには、その修飾子が完全に同一でなければなりません。
char *p = 0; const char **cpp = &p; // エラー: char* と const char* は互換性のない型です char * const *pcp = &p; // OK, 修飾子を追加 (char* から 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 型修飾子
関連項目
|
C++ ドキュメント
for
cv (
const
and
volatile
) 型修飾子
|
タグ内のconstとvolatileは翻訳せず保持
- 元のフォーマットと構造を完全に維持