5

Cではリテラルと定数は同じ概念ですか? 使用上の違いはありますか?

4

3 に答える 3

11

リテラル定数はCでは大きく異なります。Cのリテラルという用語はメモリを占有する名前のないオブジェクトを表し(リテラルは通常は左辺値です)、定数という用語は必ずしも占有しない(名前が付けられている可能性がある)値を表します。メモリ(定数は右辺値です)。

「クラシック」C(C89 / 90)には、文字列リテラルという1種類のリテラルしかありませんでした。そのCには他の種類のリテラルはありませんでした。C99は、いわゆる複合リテラルを追加で導入しました。

一方、定数1という用語は、、、、などの明示2.5f的な値0xAを指します's'。さらに、列挙型メンバーもCの定数として認識されます。

繰り返しますが、Cのリテラルは左辺値であるため、それらのアドレスを取得して使用できます

const char *s = "Hello";
char (*p)[6] = &"World";
int (*a)[4] = &(int []) { 1, 2, 3, 4 };

定数は右辺値であるため、それらのアドレスを取得することはできません。

constキーワードで宣言されたオブジェクトは、C用語では定数とは見なされません。定数値が必要な場合(ケースラベル、ビットフィールド幅、グローバルな静的変数の初期化など)には使用できません。

PS Cの関連用語は、C++の用語とはかなり異なることに注意してください。C ++では、リテラルという用語は、実際にはCで定数として知られているもののほとんどをカバーしています。また、C ++では、constオブジェクトは定数式を形成できます。人々は時々C++の用語をCに押し付けようとしますが、それはしばしば混乱を招きます。

定義よりも定数を優先しますか?も参照してください)

于 2012-07-31T04:07:16.367 に答える
5

C標準(具体的にはISO / IEC 9899、第2版、1999-12-01)はそれ自体で「リテラル」を定義していないため、これはCの特定の概念ではありません。以下に説明する「リテラル」の3つの使用法を見つけます。

まず、文字列リテラル(または正式な文法では「string-literal」)は、引用符内の文字のシーケンスであり、オプションで「L」(幅の広い文字列リテラルになります)が前に付けられます。文字列内の各文字がそれ自体を表すため、これは間違いなくリテラルと呼ばれます。ソーステキストの「b」は文字列の「b」になります。(対照的に、文字列ではなく数値としてのソーステキストの文字「34」は、文字「3」および「4」ではなく、プログラムの値34になります。)これらのリテラルのセマンティクスは、次のように定義されます。 6.4.5のパラグラフ4および5。基本的に、隣接するリテラルは連結され("abc" "def"になり"abcdef")、ゼロバイトが追加され、その結果を使用して静的ストレージ期間の配列が初期化されます。したがって、文字列リテラルはオブジェクトになります。

次に、複合リテラルは、構造の値を作成するために使用されるより複雑な構造です。「複合リテラル」は、まったくリテラルではないため、残念な名前です。つまり、リテラルのソーステキスト内の文字は、必ずしもそれ自体を表すとは限りません。実際、複合リテラルは定数ではありません。複合リテラルには、関数呼び出しなど、実行時に評価される式を含めることができます。

第三に、6.1段落1では、標準では「リテラル単語と文字セットのメンバー」は太字で示されています。この「リテラル」の使用は、C言語内で物事を説明するのではなく、標準自体を説明することです。これは、標準の「<strong>goto」がC言語の文字列「goto」を意味することを意味します。

文字列リテラルを除いて、「リテラル」はCの特定の概念ではないと思います。

ただし、「一定」は重要な概念です。

まず、「34」、「4.5f」、「'b'」などの単純な定数があります。後者は文字定数です。文字で書かれていますが、整数値です。定数には、整数定数(10進数、8進数、および16進数)、浮動定数(10進数および16進数)、文字定数、および列挙定数が含まれます。列挙型定数は、「enum」構造で指定された名前です。

次に、6.6で定義されている定数式があります。定数式は、実行時ではなく変換(コンパイル時)中に評価でき、定数が存在する可能性のある任意の場所で使用できます。6.6は定数式の特定のルールを設定します。例として、xがで宣言されている静的配列の場合static int x[8];&x[(int) (6.8 * .5)]は定数式です。これはxの要素3のアドレスです。(配列にインデックスを付けるために浮動小数点を使用することはめったにありませんが、定数式の一部として許可されていることを示すために、例に含めています。)

「const」について:この標準は、const修飾オブジェクトを定数として具体的に定義していないようです。むしろ、const修飾型で定義されたオブジェクトを、非const修飾型の左辺値(逆参照ポインターなど)を介して変更しようとすると、動作は未定義であると言います。これは、constオブジェクトの一定性を強制するためにC実装が必要ないことを意味します。(また、constへのポインターがあることは、ポイントされたオブジェクトがconstであることを意味するのではなく、逆参照されたポインターが変更可能な左辺値ではないことに注意してください。const修飾されていない同じオブジェクトへの別のポインターが存在する可能性があります。たとえば、ではint i; int *p = &i; const int *q = p;、qはconst-intへのポインタですが、iはconstオブジェクトではありません。また、pは、constなしのintへのポインタですが、同じintへのポインタです。)

于 2012-07-31T09:13:53.027 に答える
1

そうではありません。定数変数 (マクロで定義された定数とは対照的に) は、専用の記憶領域を持つ実際の変数であるため、それらのアドレスを取得できます。リテラルのアドレスを取ることはできません。

編集:申し訳ありませんが、私が間違っていたようです。

于 2012-07-31T03:58:52.080 に答える