72

C ++ 03 5.1一次式§2は次のように述べています:

リテラルは主要な式です。そのタイプはその形式(2.13)によって異なります。文字列リテラルは左辺値です。他のすべてのリテラルは右辺値です。

同様に、C996.5.1§4は次のように述べています。

文字列リテラルは主要な式です。6.4.5で詳述されているタイプの左辺値です。

この背後にある理論的根拠は何ですか?

私が理解しているように、文字列リテラルはオブジェクトですが、他のすべてのリテラルはそうではありません。また、l値は常にオブジェクトを参照します。

しかし、問題は、他のすべてのリテラルがオブジェクトではないのに、なぜ文字列リテラルがオブジェクトなのかということです。この論理的根拠は、私には卵が先か鶏が先かという問題のように思えます。

これに対する答えは、プログラミング言語としてのC / C ++ではなくハードウェアアーキテクチャに関連している可能性があることを理解していますが、それでも同じことを聞きたいと思います。

4

4 に答える 4

37

文字列リテラルは配列型のリテラルであり、Cでは、左辺値として以外に配列型が式に存在する方法はありません。文字列リテラルは、文字列「contents」を指すポインタ型(通常はポインタに減衰する配列型ではなく)を持つように指定できますが、これではあまり有用ではありません。特に、sizeof演算子はそれらに適用できませんでした。

C99は、左辺値でもある複合リテラルを導入したため、リテラルを左辺値にすることは、もはや特別な例外ではないことに注意してください。それは標準に近いです。

于 2012-04-04T03:34:03.607 に答える
17

文字列リテラルは配列です。つまり、本質的にサイズが予測できないオブジェクトです (つまり、ユーザー定義のサイズが大きい可能性があります)。一般に、そのようなリテラルをメモリ内のオブジェクトとして、つまり として表現する以外に表現する方法は他にありませんlvalues。C99 では、これは複合リテラルにも適用されlvaluesます。

文字列リテラルが言語レベルにあるという事実を人為的に隠そうlvaluesとすると、かなりの数の完全に不必要な問題が発生します。ポインターを使用して文字列リテラルを指す機能と配列としてアクセスする機能は非常に依存しているためです。言語レベルで見える左辺値性について。

一方、スカラー型のリテラルは、コンパイル時のサイズが固定されています。同時に、そのようなリテラルは、特定のハードウェア アーキテクチャのマシン コマンドに直接埋め込まれている可能性が非常に高くなります。たとえば、 のようなものを記述するとi = i * 5 + 2、リテラル値5and2は、生成されたマシン コードの明示的な (または暗黙的な) 部分になります。それらは存在せず、データ ストレージ内のスタンドアロンの場所として存在する必要もありません。値5を格納2したり、データ メモリに格納したりするだけでは意味がありません。

また、多くの (ほとんどまたはすべてではないにしても) ハードウェア アーキテクチャでは、浮動小数点リテラルが実際には "非表示" として実装されていることも注目に値しますlvalues(たとえ言語がそれらをそのように公開していなくても)。x86 のようなプラットフォームでは、浮動小数点グループからのマシン コマンドは埋め込み即値オペランドをサポートしません。つまり、ほぼすべての浮動小数点リテラルは、コンパイラによってデータ メモリに格納 (およびデータ メモリから読み取られる) される必要があります。たとえば、次のようなものを書くと、次のようなi = i * 5.5 + 2.1ものに翻訳されます

const double unnamed_double_5_5 = 5.5;
const double unnamed_double_2_1 = 2.1;
i = i * unnamed_double_5_5 + unnamed_double_2_1;

つまり、社内でfloating-point literals「非公式」になってしまうことが多いのです。lvaluesただし、言語仕様がこの実装の詳細を公開しようとしなかったことは完全に理にかなっています。言語レベルではarithmetic literals、より理にかなっていrvaluesます。

于 2012-12-06T01:40:15.417 に答える
10

C ++では、常にオブジェクトを参照するlvalueとは限りません。関数を参照することもできます。さらに、オブジェクトはによって参照される必要はありませんlvalues。それらはrvalues、配列(C ++およびC)を含め、によって参照される場合があります。ただし、古いC89では、配列からポインタへの変換は配列に適用されませんでしたrvalues

現在、anrvalueは、有効期限が切れている、制限されている、または間もなく期限切れになることを示します。ただし、文字列リテラルはプログラム全体で使用できます。

ですからstring literals、存在lvaluesは正確に正しいのです。

于 2012-04-04T08:00:25.057 に答える
10

元々の動機は主に実用的な動機だったと思います。文字列リテラルはメモリ内に存在し、アドレスを持っている必要があります。文字列リテラルの型は配列型(char[]C、char const[]C ++)であり、配列型はほとんどのコンテキストでポインターに変換されます。言語はこれを定義する他の方法を見つけることができたかもしれません(たとえば、文字列リテラルは、それが指しているものに関する特別な規則で、最初にポインタ型を持つことができます)が、リテラルを左辺値にすることは、具体的に何を定義する最も簡単な方法です。必要です。

于 2012-04-04T07:38:33.360 に答える