ヌルポインタまたは割り当てられていないメモリへのポインタの逆参照は、未定義の動作を呼び出します。無効なメモリを指しているときのsizeof(* ptr)の動作は未定義ですか?
しかし、sizeofに渡される式内で使用されるルールは何ですか?例えば
:
int* ptr = 0;
int size = sizeof(*ptr);
が、これがまた、未定義のですか?
ヌルポインタまたは割り当てられていないメモリへのポインタの逆参照は、未定義の動作を呼び出します。無効なメモリを指しているときのsizeof(* ptr)の動作は未定義ですか?
しかし、sizeofに渡される式内で使用されるルールは何ですか?例えば
:
int* ptr = 0;
int size = sizeof(*ptr);
が、これがまた、未定義のですか?
ほとんどの場合(C以上)、sizeof(*x)
は実際には*x
と評価されません。 C99標準では、これは6.5.3.4 The sizeof operator
、一部/2
(私の太字)で述べている:
sizeof演算子は、式または種類の括弧付きの名前であり、そのオペランドのサイズを(バイト単位)、得られます。サイズは、オペランドのタイプから決定されます。結果は整数です。オペランドの型が可変長配列型の場合、オペランドは評価されます。そうでない場合、オペランドは評価されず、結果は整数定数です。
したがって、すべての非VLAについて、逆参照は行われません。 *x
のタイプが VLAの場合、実行フェーズsizeof
と考えられます。コード実行中に処理する必要があるもの - コンパイル時に他のすべてを計算できます。 5.3.3. Sizeof
に示すように、わずかに異なるルールを有する++
C、一部/1
は:
sizeof演算子は、そのオペランドのオブジェクト表現のバイト数を与えます。オペランドは、評価されないオペランド(第5項)である式か、カッコで囲まれたタイプIDです。
5. Expressions
は一部/8
に用語 "未評価オペランド" を定義しています。いくつかの文脈で
、未評価のオペランドが表示されます。未評価のオペランドは評価されません。
(私がしばらく読んだことのない最も重大な冗長フレーズの1つかもしれませんが、ISO人の心が何を書いていたのか分かりません)。
番号sizeof
は演算子であり、実際の値(評価されていない)ではなく型で機能します。
オペレータであることを思い出させるために、実用的な場所で括弧を省略することをお勧めします。
int* ptr = 0;
size_t size = sizeof *ptr;
size = sizeof (int); /* brackets still required when naming a type */
これは式の評価は行われません。結果の型を判別するためにのみ解析されます。それが価値あるものとして、私は '&* ptr'も合法だと思います。 –
@ChrisLutz:ありがとう、私は答えに「評価されていない」を組み込んだ。 –
オペレータであることを覚えておくことはなぜ重要ですか? – UncleBens
sizeof(* ptr)はこの場合sizeof(int)と同じです。
はい、なぜですか?この答えは、それを立てるための少しのものが欠けています... –
ptrは整数へのポインタです。 * ptrは整数です。 sizeof(* ptr)はsizeof(整数)です。 – EricS
sizeof
およびdecltype
は、オペランドの計算型のみを評価しません。
sizeof
は必ずしもコンパイル時の構成ではないが、C++ではsizeof
に提供される式は決して評価されません。そのようなものとして、未定義の振る舞いが出現する可能性は決してありません。同様のロジックによって、決して定義されていないファンクションを呼び出すこともできます。ファンクションは実際に呼び出されないため、定義は必要ありません。SFINAEルールで頻繁に使用されるファクトです。
完全性のために、C++では(VLAを持たない)式は決して評価されない:C++ 11,5.3.3は、「オペランドは未評価オペランド(式5)の式か、タイプID。 –
乾杯、@マイクは、完全性のための答えにそれを取り入れた。 – paxdiablo