web-dev-qa-db-ja.com

sizeof(void())は正当な表現ですか?

[5.3.3/1] から、次のことがわかりました。

「sizeof」演算子は、関数または不完全な型を含む式には適用されません。

[3.9/5] から:

不完全に定義されたオブジェクト型と「cv void」は不完全な型です

とにかく、sizeofはそのオペランドを評価しないため、sizeof(void())は正当な式であると言いました(実際にはGCCがコンパイルし、結果は1です)。
反対側では、 here から、voidの説明中にsizeofは言及されません。サイズ1の型が言及されている場合も、 実装の定義サイズ。

質問はこうです:sizeof(void())は正当な表現ですか?
サイズが1であることが保証されていますか?
それともUBをもたらす法的表現ですか?それだけですか?

50
skypjack

void()は関数型(引数を取らず、何も返さない関数)であるため、sizeof()の有効な型ではありません。

58

CppReference.com-sizeof operator を見ると、文書は文字通り次のように述べています:

sizeofは、関数タイプ、不完全なタイプ、またはビットフィールドglvaluesでは使用できません。

void()は関数型なので、sizeof(void())は有効な式ではありません。

使用例では、この行にerrorコメントが表示されます。

std::cout << "size of function: " << sizeof(void()) << '\n'; // error
39
Khalil Khalaf

少し前提。

質問は、sizeof演算子の誤解から生じました。
実際、OPはvoid()sizeofのコンテキストで不完全な型を持つ式と見なし、質問自体は-whyと読むことができますsizeofは式void()を受け入れます。これは不完全な型であり、作業ドラフトで言及されているように受け入れられるべきではありません
だからこそ[3.9/5]が実際に言及されているのです。そうでなければ意味がありません。

ただし、実際には、質問には2つの興味深い質問が含まれています。

  • sizeof(void())が正当ではないのはなぜですか?
    これは、タイトル自体からの実際の質問です。

  • sizeof((void()))が正当ではないのはなぜですか?
    これはOPの意図した質問です。

以下の回答:

  • void()sizeof(void())は関数型として解釈され、 [5.3.3/1] (emphasis mine)のように不正な形式です:

    sizeof operatorは、functionまたは不完全なtypeを持つ式に、そのような括弧付きの名前には適用されません。タイプ、[...]

  • sizeof((void()))(void())は、不完全なタイプvoidsizeofは未評価のコンテキストであることに注意)を持つ式であり、forの形式が不適切です- [5.3.3/1] (エンファシス鉱山):

    sizeof operatorは、関数を持つ式または不完全型、そのようなタイプの括弧付きの名前、[...]

どちらの場合も、GCCは警告付きでコードをコンパイルします。

6
skypjack

ここでドキュメントで既に強調されているように http://en.cppreference.com/w/cpp/language/sizeof

sizeof()は、関数タイプ、不完全なタイプ、またはビットフィールドglvalueとともに使用できません。

void()は関数型であるため、sizeof()の有効な型ではありません

注意:

void()は引数を取らず、何も返さない関数です

ドキュメントから例を引用する:

//<< "size of function: " << sizeof(void()) << '\n'  // error

質問への回答:

1)いいえ、それは正当な表現ではありません。

2)1と表示されますが、警告が表示されます

3)1)と同じ。

1
ColdFire

C99参照番号からのストレートNO

セクションのドキュメントに記載されています 6.5.3.4 sizeof演算子

Sizeof演算子は、関数型または不完全な型を持つ式、そのような型の括弧で囲まれた名前、またはビットフィールドメンバーを指定する式には適用されません。

セクションの項目19および20に従って 6.2.5タイプ

  1. Void型は、空の値のセットで構成されます。 不完全なタイプです それは完了できません。
  2. ...関数型は、指定された戻り値型を持つ関数を記述します。関数型は、戻り値の型とそのパラメーターの数と型によって特徴付けられます。関数型は戻り型から派生したと言われ、戻り型がTの場合、関数型は「Tを返す関数」と呼ばれることもあります。戻り型からの関数型の構築は、「関数型の派生」と呼ばれます。

したがって、void()は不完全な型から派生した関数型であり、sizeofのオペランドとしては無効です。つまり、その戻り値はコンパイラの実装に依存し、戻り値が保証されていません

C99標準

1
WelsonJR