2012-03-19 19 views
9

クイズ:次のプログラムは何を印刷しますか?StructLayout Pack = 1は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();    
     } 
    } 
} 

回答:

8 
5 

これは私にとって非常に紛らわしいです。 boolとbyteの両方が1バイトのサイズを持ち、[StructLayout(LayoutKind.Sequential, Pack=1)]を指定すると、パディングの問題を無効にする必要があります。両方の構造体は5バイトでなければなりません。だから私は2つの質問があります:

  • マーシャルはなぜこのように動作しますか?
  • 回避策はありますか?私はインポートする必要があるネイティブ構造体に1バイトのブール値を持っています。私はバイトの代わりにもちろん使用することができますが、それは "乱雑"です。

ありがとうございます。

答えて

18

デフォルトでは、.NETタイプboolBOOLのメンバになります。typedefintです。あなたは、1バイトの管理対象外ブールにしてからマーシャリングしたい場合は、属性を持つマーシャラーにこれを示す:

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

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

これは驚異的なMicrosoft-ismです:boolはCとC++では1バイトです。マイクロソフト固有のtypedefにマーシャリングすることは決してなかったでしょう。 – Asik

+9

ブール値はCの整数(少なくともC99以前)です。 C++だけがネイティブ 'bool'型を持っています。ブール値としてint型を使用するインターオペラビリティについては、より一般的です。 – SztupY

2

boolは(C/C++プログラムは、通常はbooleanとしてintを使用して相互運用性の理由から、int32にマーシャリングますBOOLはであり、intとなっています)、したがって4バイトに変換されます。

関連する問題