名前空間
変種
操作

const 型修飾子

From cppreference.com
< c‎ | language

C の型システムにおける各型には、その型の「修飾された」バージョンがいくつか存在します。これらは、constvolatile、そしてオブジェクト型へのポインタの場合にはrestrict の 1 つ、2 つ、または 3 つすべての修飾子に対応します。このページでは、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 修飾された型のオブジェクトを指定する左辺値式、および少なくとも 1 つのメンバーが 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 修飾されませんが、その要素型は 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 を使用して)、その動作は未定義です。

関数の宣言において、キーワード const は、関数パラメータの配列型を宣言するために使用される角括弧の内側に現れることがあります。これは、配列型に変換されるポインタ型を修飾します。

以下の 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: adds qualifiers (int to const int)
p = cp; // Error: discards qualifiers (const int to int)
p = (int*)cp; // OK: cast

T へのポインタから const T へのポインタへの変換は、直接はできません。2 つの型が互換性を持つためには、その修飾子は同一である必要があります。

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 (const および volatile) 型修飾子
English 日本語 中文(简体) 中文(繁體)