web-dev-qa-db-ja.com

Cにはconstがありますか?

この質問は素朴かもしれませんが、

  • cにはconstキーワードはありますか?
  • どのバージョンから?
  • cとC++のconstの間に意味的または構文上の違いはありますか?
52
Armen Tsirunyan

CとC++の間にconstキーワードに関して構文上の違いはありませんが、かなりあいまいなものを除いて、Cでは(C99以降)関数パラメーターを次のように宣言できます。

void foo(int a[const]);

これは

void foo(int *const a);

宣言。 C++はそのような構文をサポートしていません。

意味の違いも存在します。 @Ben Voigtがすでに述べたように、Cではconst宣言は定数式を生成しません。つまり、Cではcaseラベルのconst intオブジェクトをビットとして使用できません-フィールド幅または非VLA配列宣言の配列サイズ(これはすべてC++で可能です)。また、constオブジェクトには、Cではデフォルトで外部リンケージがあります(C++の内部リンケージ)。

少なくとも1つのセマンティックの違いがありますが、ベンは言及していません。 C++言語のconst-correctnessルールは、次の標準変換をサポートしています

int **pp = 0;
const int *const *cpp = pp; // OK in C++

int ***ppp = 0;
int *const *const *cppp = ppp; // OK in C++

これらの初期化はCでは不正です。

int **pp = 0;
const int *const *cpp = pp; /* ERROR in C */

int ***ppp = 0;
int *const *const *cppp = ppp; /* ERROR in C */

一般に、マルチレベルポインターを扱う場合、C++では、最上位レベルまでconst-qualificationも追加する限り、任意の深さの間接参照でconst-qualificationを追加できると述べています。

Cでは、最上位のポインターが指す型にのみconst-qualificationを追加できますが、それより深くすることはできません。

int **pp = 0;
int *const *cpp = pp; /* OK in C */

int ***ppp = 0;
int **const *cppp = ppp; /* OK in C */

同じ基本的な原則のもう1つの兆候は、CおよびC++の配列でconst-correctnessルールが機能する方法です。 C++では次のことができます

int a[10];
const int (*p)[10] = &a; // OK in C++

Cで同じことをしようとするとエラーになります

int a[10];
const int (*p)[10] = &a; /* ERROR in C */
55
AnT

最初の2つの質問はここで答えられます: Cの定数

はい、CとC++のconstのセマンティクスにはかなりの違いがあります。

  • C++では、適切なタイプのconst変数は積分定数式(初期化子がコンパイル時の定数式の場合)であり、使用できます配列の境界などのそれを必要とするコンテキスト、および列挙型の定義で。 Cでは、そうではありません。

  • C++では、constグローバル変数は自動的にstaticリンケージを持っているため、ヘッダーファイルに配置できます。 Cでは、このような変数には外部リンケージがあり、リンク時に定義エラーが重複して生成されます。

13
Ben Voigt

はい、constキーワードがあります。 1989年の規格の一部として追加されました。

互換性に関する限り、これはHarbison&Steele、第5版の段落です。

型修飾子がconstであるが明示的なストレージクラスがないトップレベルの宣言は、C++ではstaticと見なされますが、Cではexternと見なされます。互換性を維持するには、top- level const宣言し、明示的なストレージクラスを提供します。 C++では、文字列定数は暗黙的にconstです。彼らはCではありません。
8
John Bode

他の2つの違い:

はい、constは少なくともANSI C(別名C89)以来存在しています。

それは確かに私のコピー "Cプログラミング言語(第2版)"、Kernighan&Ritchie (1988年に公開)に表示されます。

関連する抽出物:

constおよびvolatileプロパティは、ANSI標準で新しく追加されました。 constの目的は、読み取り専用メモリに配置される可能性のあるオブジェクトを通知し、おそらく最適化の機会を増やすことです。

5
GrahamS

はい。 constは、C89からCにあります。

Cのconstキーワードの動作 についての良い読み物は次のとおりです。

2
Nawaz

CのセマティックはC++とは異なります。

unsigned const a = 10;
unsigned A[a];

ファイルスコープ内はC++では有効ですが、Cでは無効です。

2
Jens Gustedt

Cには「const」キーワードがあり、長い間使用されてきました。変数が「const」と指定されている場合、その変数への書き込みは禁止されています。さらに、一部の環境では、「const」と宣言された変数が他の変数とは異なるデータセグメントに配置される場合があります。このデータセグメントは、ハードウェア書き込み保護を提供し、組み込みシステムの場合、ROMではなく、RAMまたはフラッシュメモリに保存されます(より多くのROMまたはRAMよりもフラッシュのある一部のプロセッサ-128Kフラッシュおよび3.5K RAM、または2K ROMおよび96バイトRAM)。

コンパイラは通常、 ない 「const」値またはそれらを含む式について推論します。 「const char foo [] = "Hello";」と言った場合後でfoo [1]を参照すると、コンパイラはfoo []が格納されている場所から値(ほとんどの場合 'e')をロードし、ロードされた値を使用します。これにより、コンパイルされたコードイメージで値にパッチを適用できる場合がありますが、コードが無駄になる場合もあります。

コンパイル時の「置換可能な」定数になるように数値を定義したい場合、少なくとも整数定数の場合、「列挙型」を使用するのが最善の方法です。たとえば、「enum {woozle = 19;}」と指定すると、コード全体で19が「woozle」に置き換えられます。テキスト置換とは異なり、列挙型宣言は、スコープの適切な規則に従います。

1
supercat

はい、Cにはconstキーワードがあります。C90から存在しています。

構文的には、C++と同じ場所で発生する可能性があります。意味的に、それは少し緩いです、IIRC。

1

[〜#〜] esr [〜#〜] によると、constがANSI C Draft Proposed Standardに追加されました。 1987年付けのEric GiguereによるANSI Cの要約 はそれを裏付けています。

編集: これはドラフト自体のように見えます -「3.5.3 Type qualifiers」を検索します。

1
Ken