11

Quiz: what does the following program print?

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();            
        }
    }
}

Answer:

8
5

This is very confusing to me. Both bool and byte have a size of 1 byte, and specifying [StructLayout(LayoutKind.Sequential, Pack=1)] should nullify any padding issues. Both structs should be 5 bytes. So I have two questions:

  • Why does marshalling work this way?
  • Any workaround? I have 1-byte booleans in native structs I need to import. I can use byte instead of course but it's "messy".

Thanks.

Asik
  • 21,506
  • 6
  • 72
  • 131

2 Answers2

23

By default, .NET type bool marshals to unmanaged type BOOL, which is typedefed to int. If you want to marshal to and from 1-byte unmanaged booleans, indicate this to the marshaler with an attribute:

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

Console.WriteLine (Marshal.SizeOf (typeof (Struct3))) ; // prints 5
Anton Tykhyy
  • 19,370
  • 5
  • 54
  • 56
  • That's a glaring Microsoft-ism: bool is 1 byte in C and C++. It would have never occured to me that they would marshal to a Microsoft-specific typedef. – Asik Mar 19 '12 at 08:07
  • 11
    booleans are just integers in C (at least pre-C99). Only C++ has a native `bool` type. For interoperability using `int` as boolean is better, as it's more common. – SztupY Mar 19 '12 at 08:49
3

bool gets Marshalled to an int32, for interoperability reasons (C/C++ programs usually use int as booleans, and in winapi BOOL is typedefed as an int as well), therefore it's converted to 4 bytes.

SztupY
  • 10,291
  • 8
  • 64
  • 87