43

Why does a System.Boolean take 4 bytes? It just stores one state, either true or false, which could be stored in less space than 4 bytes.

P Daddy
  • 28,912
  • 9
  • 68
  • 92
Sun
  • 2,110
  • 2
  • 21
  • 28

6 Answers6

61

A bool is actually only 1 byte, but alignment may cause 4 bytes to be used on a 32-bit platform, or even 8 bytes on a 64-bit platform. For example, the Nullable<bool> (aka bool?) type uses a full 32 or 64 bits—depending on platform—even though it's comprised of just two bools. EDIT: As pointed out by Jon Skeet, padding for alignment isn't always present. As an example, an array of Nullable<bool>s takes only 2 bytes per object instead of 4 or 8.

But even 8 bits to represent a bool can be considered wasteful if you have many of them to store. For this reason, if you create a type that has many bools as members, (or uses many Nullable<> types), and users of your class might create many instances of it, you might consider using a BitVector32 instead. The framework itself uses this technique to reduce the memory footprint of many of the Windows Forms controls, for instance.

P Daddy
  • 28,912
  • 9
  • 68
  • 92
  • 3
    Even Nullable will only use up two bytes in some cases - for instance if you've got an array of them. – Jon Skeet Nov 17 '08 at 06:26
  • Yes, you're right. I would have expected it to align array indices for performance's sake, but it doesn't seem to. – P Daddy Nov 17 '08 at 07:32
  • This is an artifact of the C standard library and compiler. Most compilers on 32-bits and 64-bits platforms where memory is not really an issue optimize for performance, not code size. Bools are not packed by the compiler into bitfields, unless done explicitly in a struct. This is to keep adequate performance when passing pointers, otherwise you not only have to dereference but also mask on every access. – Drunken Code Monkey Jun 23 '16 at 05:14
14

Because it's fast.

A 32-bit processor typically works with 32-bit values. Working with smaller values involves longer instructions, or extra logic.

Artelius
  • 48,337
  • 13
  • 89
  • 105
5

The first result on a Google search for System.Boolean size told me that it's to do with memory alignment. It's faster to push around a four-byte Int32 than it is to work with individual bytes/bits.

Matt Hamilton
  • 200,371
  • 61
  • 386
  • 320
  • 6
    Today's first Google answer is this question. Since questions are archived, please add also the specific link in the future. – Blaisorblade Oct 18 '11 at 13:05
2

I think it's only for performance, 32 bit values are much more efficient to manipulate.

Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
2

Where'd you get that? System.Boolean takes only 1 byte.

Just try:

Console.WriteLine( sizeof( System.Boolean ).ToString() );
arul
  • 13,998
  • 1
  • 57
  • 77
  • Check the size after the type has been marshaled: Console.Write(System.Runtime.InteropServices.Marshal.SizeOf(new System.Boolean())); – Christian C. Salvadó Nov 17 '08 at 05:06
  • Which is what you shouldn't do. Most of the unmanaged API's use *int* for BOOL values, Marhsal.SizeOf() tells you size of an *unmanaged* type. – arul Nov 17 '08 at 05:10
  • Marshalling a bool is slighly more complicated than that. I did a blog post on this subject which covers the various sizes: http://blogs.msdn.com/jaredpar/archive/2008/10/14/pinvoke-and-bool-or-should-i-say-bool.aspx – JaredPar Nov 17 '08 at 06:42
  • I used the GC.GetTotalMemory to check it... my post was too long to fit here in the replies but I added it as a response to this question for anyone who is interested. – John Fairbanks Feb 14 '14 at 16:45
0

I used the following code to create a couple arrays and test them. float?[100000] uses twice as much memory as float[100000]. This is because the bool that accompanies the float in the float? case gets aligned to 32 bits (at least on my machine ;-) )

long startMem = 0, stopMem = 0;
DateTime startTime = DateTime.Now;
private void StartMemoryUsage()
{
    GC.Collect();
    GC.Collect();
    startMem = GC.GetTotalMemory(true);
    startTime = DateTime.Now;
}
private void StopMemoryUsage()
{
    GC.Collect();
    GC.Collect();
    stopMem = GC.GetTotalMemory(true);

    Console.WriteLine("---> {0} sec.  Using {1} KB.", (DateTime.Now - startTime).TotalSeconds, ((stopMem - startMem) / 1000).ToString());
}
John Fairbanks
  • 1,342
  • 12
  • 16