10

LayoutKind.Explicit属性が設定された構造について少し質問があります。structご覧のfieldTotalとおり、64ビットでfieldFirst最初の32バイトとfieldSecond最後の32バイトを宣言しました。との両方fieldfirstを設定fieldSecondした後Int32.MaxValue、私はになると期待fieldTotalしますがInt64.MaxValue、実際には起こりません。どうしてこれなの?C#は実際にはC ++共用体をサポートしていないことを知っています。おそらく、相互運用時に値を適切に読み取るだけですが、自分で値を設定しようとすると、実際にはうまく処理されません。

[StructLayout(LayoutKind.Explicit)]
struct STRUCT {
    [FieldOffset(0)]
    public Int64 fieldTotal;

    [FieldOffset(0)]
    public Int32 fieldFirst;

    [FieldOffset(32)]
    public Int32 fieldSecond;
}

        STRUCT str = new STRUCT();
        str.fieldFirst = Int32.MaxValue;
        str.fieldSecond = Int32.MaxValue;
        Console.WriteLine(str.fieldTotal); // <----- I'd expect both these values
        Console.WriteLine(Int64.MaxValue); // <----- to be the same.
        Console.ReadKey();
4

3 に答える 3

10

その理由は、FieldOffsetAttributeがパラメーターとしてビット数ではなくバイト数を受け取るためです。これは期待どおりに機能します。

[StructLayout(LayoutKind.Explicit)]
struct STRUCT
{
    [FieldOffset(0)]
    public Int64 fieldTotal;

    [FieldOffset(0)]
    public Int32 fieldFirst;

    [FieldOffset(4)]
    public Int32 fieldSecond;
}
于 2009-07-21T23:27:43.487 に答える
6

Int32.MaxValueとInt64.MaxValueが答えを提供する必要がある場合は、16進値を調べます。

キーは最上位ビットです。正の整数の場合、最上位ビットは負の数にのみ設定されます。したがって、Int32の最大値は0で、その後に一連の1が続きます。順序は重要ではなく、少なくとも1つの0ビットが存在するだけです。同じことがInt64.MaxValueにも当てはまります。

次に、組合がどのように機能するかを考えてみましょう。基本的に、値のビットを並べて配置します。これで、2つの0ビット値を含む長さ64のビットのセットができました。Int32.MaxValueインスタンスごとに1つ。これは、単一の0ビットしか含めることができないため、Int64.MaxValueと等しくなることはありません。

奇妙なことに、fieldSecondをInt32.MinValueに設定すると、探している動作が得られる可能性があります。

編集あなたもそれをFieldOffset(4)にする必要があることを見逃しました。

于 2009-07-21T23:25:36.093 に答える
5

ベンMはより重要な要素の1つを提供しました-あなたの定義は正しく設定されていません。

そうは言っても、これは機能しません-ユニオンを使用するC++でも機能しません。符号付き(符号なしではない)intを使用しているため、指定した値は同じ値にはなりません(また、同じ値であってはなりません)。符号付き整数(Int32)を使用すると、0ビットの後に1ビットが続きます。ユニオンを実行すると、0ビット、1ビットの束、さらに0ビット、1ビットの束が続きます...2番目の0ビットはあなたを混乱させるものです。

UInt32 / UInt64を使用した場合、余分な符号ビットが存在しないため、これはプロパティで機能します。

于 2009-07-21T23:28:38.040 に答える