2009-07-21 27 views
9

Tôi có một câu hỏi nhỏ về cấu trúc với tập hợp thuộc tính LayoutKind.Explicit. Tôi đã tuyên bố số struct như bạn có thể thấy, với số fieldTotal có 64 bit, là fieldFirst 32 byte đầu tiên và fieldSecond 32 byte cuối cùng. Sau khi đặt cả hai số fieldfirstfieldSecond thành Int32.MaxValue, tôi mong đợi fieldTotalInt64.MaxValue, điều thực sự không xảy ra. Tại sao điều này? Tôi biết C# không thực sự hỗ trợ các công đoàn C++, có lẽ nó sẽ chỉ đọc các giá trị tốt khi interoping, nhưng khi chúng ta cố gắng thiết lập các giá trị bản thân nó đơn giản sẽ không xử lý nó thực sự tốt?Làm thế nào tôi có thể mô phỏng một liên minh C++ trong 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(); 

Trả lời

10

Lý do là FieldOffsetAttribute lấy một số byte làm tham số - không phải số bit. Này hoạt động như mong đợi:

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

    [FieldOffset(0)] 
    public Int32 fieldFirst; 

    [FieldOffset(4)] 
    public Int32 fieldSecond; 
} 
+0

Cộng với những gì Reed & Jared nói về chữ ký và chưa ký. –

6

Nhìn vào giá trị hex nếu Int32.MaxValue và Int64.MaxValue sẽ cung cấp câu trả lời.

Điều quan trọng là bit quan trọng nhất. Đối với một số nguyên dương, bit quan trọng nhất chỉ được đặt cho một số âm. Vì vậy, giá trị tối đa của Int32 là 0 theo sau là một chuỗi toàn bộ 1s. Thứ tự là không quan trọng, chỉ rằng sẽ có ít nhất một bit 0. Điều này cũng đúng với Int64.MaxValue.

Bây giờ, hãy xem xét cách thức hoạt động của công đoàn. Về cơ bản nó sẽ bố trí các bit của các giá trị bên cạnh nhau. Vì vậy, bây giờ bạn có một bộ bit 64 chiều dài có chứa hai giá trị 0 bit. Một cho mỗi phiên bản Int32.MaxValue. Điều này không bao giờ có thể bằng Int64.MaxValue vì nó chỉ có thể chứa một bit 0.

Rất kỳ quặc, bạn có thể sẽ nhận được hành vi bạn đang tìm kiếm nếu bạn đặt trườngSecond thành Int32.MinValue.

EDIT Bỏ lỡ bạn cũng cần đặt FieldOffset (4).

4

Ben M cung cấp một trong những yếu tố quan trọng hơn - định nghĩa của bạn không được thiết lập một cách chính xác.

Điều đó đang được nói, điều này sẽ không hoạt động - ngay cả trong C++ với công đoàn. Các giá trị bạn chỉ định sẽ không (và không nên là) các giá trị giống nhau, vì bạn đang sử dụng các ký tự int (chưa được ký). Với một int đã ký (Int32), bạn sẽ có một bit 0 theo sau là 1 bit. Khi bạn làm công đoàn, bạn sẽ kết thúc với một bit 0, tiếp theo là một bó của 1 bit, sau đó một bit 0, sau đó một bó 1 bit ... bit thứ hai 0 là những gì gây rối bạn.

Nếu bạn sử dụng UInt32/UInt64, thuộc tính này sẽ hoạt động vì bit dấu phụ không tồn tại.

+0

Có, bạn đã đúng. Với những gì bạn nói và Ben nói, nó hoạt động như mong đợi. Cảm ơn! –

Các vấn đề liên quan