Namespaces
Variants

const type qualifier

From cppreference.net

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 の使用による)で宣言された場合、動作は未定義です。

関数宣言において、キーワード 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: 修飾子を追加 (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 へ)

目次

翻訳の説明: - 「Contents」を「目次」に翻訳しました - HTMLタグ、属性、クラス名はすべて保持されています - ` `内のテキストはC++関連の用語(Keywords, Notes, References, See also)であるため、翻訳せずに保持しています - 数字や書式設定はすべて元のまま保持されています

キーワード

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 ) 型修飾子
翻訳のポイント: - "C++ documentation" → "C++ ドキュメント"(C++は固有名詞として保持) - "for" → "for"(技術文脈でそのまま使用) - "cv type qualifiers" → "cv 型修飾子"(cvはC++の専門用語として保持) - HTMLタグ、属性、 タグ内のconstとvolatileは翻訳せず保持 - 元のフォーマットと構造を完全に維持