2012-03-19 8 views
9

Quiz: cosa stampa il seguente programma?StructLayout Pack = 1 non funziona con bool?

using System; 
using System.Runtime.InteropServices; 

namespace ConsoleApplication2 { 

    [StructLayout(LayoutKind.Sequential, Pack=1)] 
    struct Struct1 { 
     bool b; 
     int i; 
    } 

    [StructLayout(LayoutKind.Sequential, Pack=1)] 
    struct Struct2 { 
     byte b; 
     int i; 
    } 

    class Program { 
     static void Main(string[] args) { 
      Console.WriteLine(Marshal.SizeOf(typeof(Struct1))); 
      Console.WriteLine(Marshal.SizeOf(typeof(Struct2))); 
      Console.ReadKey();    
     } 
    } 
} 

Risposta:

8 
5 

Questo è molto confuso per me. Sia bool che byte hanno una dimensione di 1 byte e la specifica di [StructLayout(LayoutKind.Sequential, Pack=1)] dovrebbe annullare tutti i problemi di riempimento. Entrambe le strutture dovrebbero essere 5 byte. Quindi ho due domande:

  • Perché il marshalling funziona in questo modo?
  • Qualsiasi soluzione alternativa? Ho booleani da 1 byte nelle strutture native che devo importare. Posso usare byte invece, naturalmente, ma è "disordinato".

Grazie.

risposta

18

Per impostazione predefinita, il tipo .NET bool commissari di tipo non gestito BOOL, che è typedef ed a int. Se si vuole schierare da e per 1 byte booleani non gestiti, indicarlo al marshalling con un attributo:

[StructLayout (LayoutKind.Sequential, Pack=1)] 
struct Struct3 { 
    [MarshalAs (UnmanagedType.I1)] 
    bool b; 
    int i; 
} 

Console.WriteLine (Marshal.SizeOf (typeof (Struct3))) ; // prints 5 
+0

Questo è un lampante Microsoft-ism: bool è 1 byte in C e C++. Non mi sarebbe mai venuto in mente che avrebbero effettuato il marshalling su un typedef specifico di Microsoft. I booleani – Asik

+9

sono solo interi in C (almeno pre-C99). Solo C++ ha un tipo 'bool' nativo. Per l'interoperabilità usando 'int' come booleano è meglio, in quanto è più comune. – SztupY

2

bool ottiene marshalling a un int32, per ragioni di interoperabilità (C/C++ di solito usano int come booleani , e in winapi BOOL è typedef ed int e quindi è convertito in 4 byte.