2012-03-19 11 views
9

Pregunta: ¿qué imprime el siguiente programa?StructLayout Pack = 1 no funciona 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();    
     } 
    } 
} 

Respuesta:

8 
5 

Esto es muy confuso para mí. Tanto bool como byte tienen un tamaño de 1 byte y especificar [StructLayout(LayoutKind.Sequential, Pack=1)] debe anular cualquier problema de relleno. Ambas estructuras deben tener 5 bytes. Así que tengo dos preguntas:

  • ¿Por qué funciona el marshalling de esta manera?
  • ¿Alguna solución alternativa? Tengo booleanos de 1 byte en estructuras nativas que necesito importar. Puedo usar byte en lugar de curso, pero es "desordenado".

Gracias.

Respuesta

18

Por defecto, tipo de .NET bool mariscales a no administrado tipo BOOL, que es typedef ed a int. Si desea reunir hacia y desde 1 byte booleanos no administrados, lo indicará al contador de referencias con un atributo:

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

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

Eso es un Microsoft-ismo deslumbrante: bool es de 1 byte en C y C++. Nunca se me hubiera ocurrido que se dirigirían a un typedef específico de Microsoft. – Asik

+9

booleanos son simplemente enteros en C (al menos antes de C99). Solo C++ tiene un tipo nativo "bool". Para la interoperabilidad, usar 'int' como boolean es mejor, ya que es más común. – SztupY

2

bool consigue movilizados a una int32, por razones de interoperabilidad (/ C++ programas en C suelen utilizar int como booleanos , y en winapi BOOL es typedef ed como int también), por lo tanto, se convierte a 4 bytes.