質問

C++のC.1.3では(2003。それはC++11にもあります)、標準はISO CとC++の違いを指摘しています;すなわち、

char arr[100];

sizeof(0, arr) 戻り値 sizeof(char*) Cでは、しかし 100 C++で。

私はのための文書を見つけることができません sizeof 二つの引数を取ります。明らかなフォールバックはコンマ演算子ですが、私はそうは思わない: sizeof(arr) Cでは 100; sizeof(0, arr)sizeof(char*).両方 sizeof(0, arr)sizeof(arr)100 C++で。

この文脈では、ISの全体のポイントが欠落している可能性があります。誰でも助けることができますか?これは09年に議論された質問に似ていますが、誰もISに言及しておらず、正しい答えが与えられたとは思いません。


編集:実際には、isはコンマ演算子について話しています。だから、何らかの理由で (0, arr) aを返します char* Cでは、しかしa char[100] C++で。どうして?

役に立ちましたか?

解決

Cでは、右辺値と左辺値に関連するコンマ演算子の仕様が異なるため、配列はポインタに減衰しています(そのような違いが見つかるのは唯一の場C++では、配列は配列のままであり、正しい結果が得られます。

他のヒント

Cでは、コンマ演算子は左辺値を生成せず、その結果、配列は左辺値を生成しません arr これは左辺値です 崩壊 (この場合は)右辺値であるポインタ型に。だから sizeof(0,arr) と同等になります sizeof(char*), のために、 左辺値から右辺値へ 変換。

しかし、C++では、コンマ演算子は左辺値を生成します。いいえありません 左辺値から右辺値へ 変換。だから sizeof(0,arr) 同じままであり、これは次のものと同等です sizeof(char[100]).

ところで, sizeof 関数ではなく、演算子です。したがって、以下は完全に有効なC++(およびc、あなたが想像すれば printf の代わりに cout):

int a[100], b[200], c[300], d[400];
cout << sizeof(a,b,c,d) << endl;

デモ : http://www.ideone.com/CtEhn

あなたは私が4つのオペランドを渡したと思うかもしれません sizeof しかし、それは間違っています。 sizeof 上で動作します その結果 コンマ演算子の。そして、その理由は、多くのオペランドを参照してください多くのコンマ演算子の。

4つのオペランドと3つのコンマ演算子;ちょうどのように 1+2+3+4, 、3つの演算子、4つのオペランドがあります。

上記は次のものと同等です(C++0xで有効):

auto & result = (a,b,c,d); //first all comma operators operate on the operands.
cout << sizeof (result) << endl; //sizeof operates on the result

デモ : http://www.ideone.com/07VNf

だからそれは コンマ あなたを作る演算子 感じる 多くの人がいること 引数.ここに コンマ は演算子ですが、関数呼び出しでは, コンマ は演算子ではなく、単に引数の区切り文字です。

function(a,b,c,d); //here comma acts a separator, not operator.

だから sizeof(a,b,c,d) 上で動作します タイプ の結果の , 演算子は、まったく同じ方法で, sizeof(1+2+3+4) 上で動作します タイプ の結果の + 演算子。

また、あなたに注意してください できません 書き込み sizeof(int, char, short), 正確には、 コンマ オペレータは操作できません タイプ.それは動作します のみ。私は思う, sizeof は、cおよびC++の唯一の演算子であり、動作することができます タイプ 同様に。C++では、操作できる演算子がもう1つあります タイプ.その名前は typeid.

これはコンマ演算子です。そして、あなたが話している違いは絶対に何の関係もありません sizeof.違いは、実際には左辺値から右辺値、配列からポインタ、およびC言語とC++言語の間の同様の減衰動作にあります。

この点でC言語はむしろトリガーに満足しています:配列は実質的にすぐにポインタに減衰します(ごく少数の特定のコンテキストを除いて)。 0, arr 式は持っています char * タイプ。これは次のものと同等です 0, (char *) arr.

C++言語では、配列は"配列性"をはるかに長く保持します。のコンテキストで使用される場合 , 演算子配列はポインタに減衰しません(左辺値は右辺値に減衰しません)。 0, arr 式はまだです char[100].

これは違いを説明するものです sizeof その例での動作。 ?: 演算子は、減衰挙動の同様の違いを示す演算子の別の例です。 sizeof(0 ? arr : arr) CとC++では異なる結果が得られます。基本的に、それはすべて、C演算子が通常、オペランドの左辺値を保持しないという事実に由来します。この動作を実証するために多くの演算子を使用できます。

これはそうではありません sizeof 二つの引数を取ります。 sizeof は演算子であり、関数ではありません。

それを考えてみましょう (0, arr) はコンマ演算子を使用した式であり、他のすべてが所定の位置に落ちます。

sizeof 二つの引数を取りません。しかし、それはどちらか、機能ではありません, だから、 (...) 関数の引数を区切るのではなく、単に 構文のオプション部分、およびグループ化を強制します。あなたが書くとき sizeof(0, arr), 、への引数 sizeof は単一の式です 0, arr.コンマ演算子を持つ単一の式で、次の式を評価します コンマの左側にある式は、その値をスローします(ただし、その値はスローしません 副作用)、コンマの右側にある式を評価します, そして、その値を完全な式の値として使用します。

私はCについてはよくわかりませんが、これはcの違いかもしれません ランゲスC++では、配列からポインタへの変換は次の場合を除き発生しません それは必要です;Cでは、私が正しく思い出すと、標準はそれを言っています 特定の状況を除いて常に行われます。として含む の演算子 sizeof.この場合、コンマ演算子はそうではないので そのオペランドの型に関して制約を持っている、 配列からポインタへの変換はC++では行われません。Cでは、 コンマ演算子のoperatandは例外にリストされていないので、 配列からポインタへの変換が行われます。(この場合、配列は はコンマ演算子のオペランドであり、コンマ演算子のオペランドではありません sizeof.)

ここで何が起こっているのかを確認する最良の方法は、標準の文法を見ることです。ドラフトC99標準のセクションを見ると 6.5.3 単項演算子 パラグラフ 1 sizeofの文法は次のようになっていることがわかります:

sizeof unary-expression
sizeof ( type-name )

だから、第二のものは適用されませんが、どのように sizeof unary-expression この場合に適用されますか?私たちはセクションを見れば A.2.1 ドラフト標準から、次のような文法を介して作業します:

unary-expression -> postfix-expression -> primary-expression -> ( expression )

私たちは、周りの括弧を取得します そして今、私たちはちょうどのための文法を見ている コンマ演算子 セクションから 6.5.17 コンマ演算子 そして、私たちは見る:

expression:
  assignment-expression
  expression , assignment-expression

だから我々は今持っている:

sizeof( expression , assignment-expression )
                   ^
                   |
                   comma operator

両方 代入式 私達をに連れて行くことができます プライマリ式 これは次の文法を持っています:

primary-expression:
  identifier
  constant
  string-literal
  ( expression )

0 である。 定数arr である。 識別子 だから私たちは持っています:

 sizeof( constant , identifier )

だから何をしますか コンマ演算子 ここでやる?セクション 6.5.17 パラグラフ 2 言っています:

コンマ演算子の左オペランドは、void式として評価されます;があります。 その評価後のシーケンスポイント。次に、右オペランドが評価されます;結果にはその型と値があります。97)

コンマ演算子は、配列がポインタに変換されない例外の1つではないため、ポインタ(これはセクションでカバーされています 6.3.2.1 左辺値、配列、および関数指定子)ということは、私たちが終わることを意味します:

sizeof( char * )

C++ 文法はかなり似ているので、同じ場所で終わりますが、コンマ演算子の動作は異なります。C++ドラフト標準セクション 5.18 コンマ演算子 言っています:

[...]結果の型と値は、右オペランドの型と値です;結果は、その右オペランド[と同じ値カテゴリになります。..]

だからと 配列からポインタへ 変換は必要ありませんので、我々はで終わる:

sizeof( char[100] ) 

すでにいくつか述べたように、私は1つだけ追加したいと思いますが、sizeofは式またはキャスト式のいずれかを取る演算子です。このため、私はsizeofにパラテーゼを書く習慣を取りました のみ キャスト式の場合。

 char *arr;
 struct xxx { ... } v;

私は書きます

sizeof arr 
sizeof v

しかし、

sizeof (struct xxx)       /* Note the space after the sizeof, it's important */
sizeof (char *)

私は同じことをします return 関数呼び出しではないため、括弧はありません。括弧を付けると、次の式がそれらを必要とするためです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top