What is the size of a boolean In C#? Does it really take 4-bytes?

后端 未结 2 759
遇见更好的自我
遇见更好的自我 2020-12-22 16:03

I have two structs with arrays of bytes and booleans:

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 4)]
struct struct1
{         


        
2条回答
  •  礼貌的吻别
    2020-12-22 16:20

    Firstly, this is only the size for interop. It doesn't represent the size in managed code of the array. That's 1 byte per bool - at least on my machine. You can test it for yourself with this code:

    using System;
    class Program 
    { 
        static void Main(string[] args) 
        { 
            int size = 10000000;
            object array = null;
            long before = GC.GetTotalMemory(true); 
            array = new bool[size];
            long after = GC.GetTotalMemory(true); 
    
            double diff = after - before; 
    
            Console.WriteLine("Per value: " + diff / size);
    
            // Stop the GC from messing up our measurements 
            GC.KeepAlive(array); 
        } 
    }
    

    Now, for marshalling arrays by value, as you are, the documentation says:

    When the MarshalAsAttribute.Value property is set to ByValArray, the SizeConst field must be set to indicate the number of elements in the array. The ArraySubType field can optionally contain the UnmanagedType of the array elements when it is necessary to differentiate among string types. You can use this UnmanagedType only on an array that whose elements appear as fields in a structure.

    So we look at ArraySubType, and that has documentation of:

    You can set this parameter to a value from the UnmanagedType enumeration to specify the type of the array's elements. If a type is not specified, the default unmanaged type corresponding to the managed array's element type is used.

    Now looking at UnmanagedType, there's:

    Bool
    A 4-byte Boolean value (true != 0, false = 0). This is the Win32 BOOL type.

    So that's the default for bool, and it's 4 bytes because that corresponds to the Win32 BOOL type - so if you're interoperating with code expecting a BOOL array, it does exactly what you want.

    Now you can specify the ArraySubType as I1 instead, which is documented as:

    A 1-byte signed integer. You can use this member to transform a Boolean value into a 1-byte, C-style bool (true = 1, false = 0).

    So if the code you're interoperating with expects 1 byte per value, just use:

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.I1)]
    public bool[] values;
    

    Your code will then show that as taking up 1 byte per value, as expected.

提交回复
热议问题