10

LayoutKind.Explicit我对具有属性集的结构有一个小问题。struct如您所见,我声明了fieldTotal64 位,fieldFirst即前 32 个字节和fieldSecond后 32 个字节。在将fieldfirstand设置fieldSecond为之后Int32.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();
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 应该提供答案,请查看十六进制值。

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

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

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

编辑错过了您也需要将其设为 FieldOffset(4) 。

于 2009-07-21T23:25:36.093 回答
5

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

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

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

于 2009-07-21T23:28:38.040 回答