如何在C#中模拟C++联合?

dev*_*ium 9 .net c# c++ struct unions

关于具有LayoutKind.Explicit属性集的结构,我有一个小问题.struct正如您所见,我声明了fieldTotal64位,fieldFirst即前32个字节和fieldSecond最后32个字节.既设置完毕后fieldfirst,并fieldSecondInt32.MaxValue,我希望fieldTotalInt64.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();
Run Code Online (Sandbox Code Playgroud)

Ben*_*n M 10

原因是FieldOffsetAttribute将多个字节作为参数 - 而不是位数.这按预期工作:

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

    [FieldOffset(0)]
    public Int32 fieldFirst;

    [FieldOffset(4)]
    public Int32 fieldSecond;
}
Run Code Online (Sandbox Code Playgroud)


Jar*_*Par 6

如果Int32.MaxValue和Int64.MaxValue应该提供答案,请查看十六进制值.

关键是最重要的一点.对于正整数,最高有效位仅设置为负数.所以Int32的最大值是0,后跟整个1s的系列.顺序并不重要,只需要至少有一个0位.Int64.MaxValue也是如此.

现在考虑一个联盟应该如何运作.它基本上会将值的位置彼此相邻.所以现在你有一组64位长度,包含两个0位值.每个Int32.MaxValue实例一个.这不能等于Int64.MaxValue,因为它只能包含一个0位.

奇怪的是,如果将fieldSecond设置为Int32.MinValue,您可能会得到您正在寻找的行为.

编辑错过了你需要使它成为FieldOffset(4).


Ree*_*sey 5

Ben M提供了更重要的元素之一 - 您的定义设置不正确。

话虽如此,这行不通——即使在带有联合的 C++ 中也是如此。您指定的值不会(也不应该是)相同的值,因为您使用的是有符号(非无符号)整数。使用有符号整数 (Int32),您将有一个 0 位,后跟 1 个位。当你做联合时,你会得到一个 0 位,然后是一堆 1 位,然后是另一个 0 位,然后是一堆 1 位......第二个 0 位是什么让你搞砸了。

如果您使用 UInt32/UInt64,这将起作用,因为额外的符号位不存在。