9
#include <iostream>

using namespace std;

class Empty{
    char omg[0];
};

int main()
{
    Empty em1, em2;
    Empty set[100];
    cout << sizeof(Empty) << " " << sizeof(em1) << " " << sizeof(em2) << endl;
    cout << (long*)&em1 << " " << (long*)&em2 << endl;

    cout << "total numbers of element is: " << sizeof(set)/sizeof(*set) << endl;

    return 0;
}

その出力は次のとおりです。

0 0 0

0xbff36ad0 0xbff36ac8

要素数: 4

結果はとても驚くべきものです。

上記のように、Empty はクラスであり、そのサイズとそのオブジェクトはすべて 0 です。なぜですか?

たぶん、空のクラスのサイズは 1 であり、クラスが空でない場合、そのサイズはメンバーによって決定されるためだと思いますが、ここではそのメンバーは特別であり、長さゼロの配列であり、この配列のサイズは 0 です。クラスとオブジェクトのサイズはすべて 0 です。

それは私の推測です。プログラムを実行すると、2 つのオブジェクトの両方にアドレスがあり、アドレスが異なることがわかります。

ここで私の質問です: サイズが 0 のオブジェクトを実装できる場合、なぜ C++ 標準は空のオブジェクトが sizeof() = 1 であると述べているのですか? それは「2 つの異なるオブジェクトのアドレスが異なることを保証するため」のためですゼロではない空のクラスの?、しかし今、出力として異なるアドレスがあります。これはどのように起こりますか?

さらに、配列セットのサイズに関係なく、最後の行の出力は常に 4 です。なぜですか?

ありがとう :)

PS: このプログラムは MacOS で実行しています。コンパイラは Apple LLVM バージョン 5.1 (clang-503.0.40) (LLVM 3.4svn ベース) です。

4

1 に答える 1

1

経験豊富な人は誰もいないので、私は突き刺します:

上記のように、Empty はクラスであり、そのサイズとそのオブジェクトはすべて 0 です。なぜですか?

サイズがゼロの配列は標準で禁止されているため、標準が無意味な式である限りsizeof(Empty)、あなたはすでに未定義の動作の領域にいます。

ここに私の質問があります: サイズが 0 のオブジェクトを実装できる場合、[...] 空のクラスのサイズがゼロでないのはなぜですか? 、しかし今、出力として異なるアドレスがあります。これはどのように起こりますか?

上記のように、サイズ 0 のオブジェクトは、有効な標準 C++ プログラムには存在できません (基底クラスのサブオブジェクトを除く)。

コンパイラはこれを標準の拡張として許可しており、この拡張を意図された範囲内で (つまり、事前に柔軟な配列メンバーのハックとして) 使用する限り、問題はないはずですが、コードはそうではありません。ポータブル。ただし、上記の例は、サイズがゼロの配列の使用方法ではありません(これらの状況を処理するための c++ のより良い構造があることは言うまでもありません)。

em1あなたのコンパイラはとに別々のアドレスを提供するのに十分なほどインテリジェントですが、 のすべての要素が実際には同じアドレスを持っていることem2がわかるはずです。set

さらに、配列セットのサイズに関係なく、最後の行の出力は常に 4 です。なぜですか?

コンパイラはsizeof(Empty)と の配列をEmptyゼロと見なすため、未定義の動作であるゼロで除算しています。最適化を無効にすると、プログラムがクラッシュする可能性があります。たとえば、GCC を使用すると、プログラムはクラッシュします-O0が、-O1.

于 2014-09-16T12:48:05.150 に答える