8
// <windef.h>

typedef int                 BOOL;

Isn't this a waste of memory since an int is 32 bits?

Just in case I was wrong, I tried sending a normal bool* to a function that required BOOL* and didn't work until I used the typedef int.

y2k
  • 65,388
  • 27
  • 61
  • 86
  • 6
    once upon a time, `bool` was no C type. See http://stackoverflow.com/questions/1608318/is-bool-a-native-c-type – dyp Jun 20 '12 at 23:30
  • 1
    oman I am so dum I am real dum for real – y2k Jun 20 '12 at 23:31
  • I knew that BUT bool was added to C so what's the HOLDUP HERE – y2k Jun 20 '12 at 23:31
  • 2
    Do you know how long that typedef has been there for? – Jesse Good Jun 20 '12 at 23:32
  • I'd guess binary compatibility. Old programs expect the API to take and return 4 bytes, not bool. – dyp Jun 20 '12 at 23:36
  • sometimes BOOL is usefull, ie. when besides TRUE and FALSE, you want to have indetermined state - then set it to -1 – marcinj Jun 20 '12 at 23:36
  • 5
    @luskan **NEVER EVER EVER EVER** do that. Someone who is used to a **sane** BOOL of 1/0 will be royally screwed when your -1 is interpreted by the program as TRUE. If you must do something like that, *use a different name*, and make it an enum. – Jonathon Reinhart Jun 20 '12 at 23:40
  • 1
    @JonathonReinhart Pfft. I seem them do it on thedailywtf.com all the time. Take the useful FILE_NOT_FOUND case, for instance... ;-) But for real, some WinAPI (or what it just VB6?) uses a troolean I think...? –  Jun 20 '12 at 23:46
  • 1
    Don't get me wrong, I use `bool?` in C# all the time. Sometimes you don't *know* if something is true or false yet. But, `bool?` cannot be cast to `bool`, so the compiler keeps you from doing something stupid. – Jonathon Reinhart Jun 20 '12 at 23:50
  • @JonathonReinhart No, no, I agree with you entirely ;-) But I do believe that returning a "non boolean" actually does exist in some of the WinAPI stuff... or I had a bad nightmare and that is all I can "remember". –  Jun 20 '12 at 23:51
  • @JonathonReinhart I agree, using enum would be the preferred solution, at least it would look better, but it would still not protect somebody from writing something like: enum NullableBool { NB_T, NB_F, NB_N } nb = NB_N; if ( nb ) { /*opps!*/} – marcinj Jun 21 '12 at 10:10
  • @luskan You're right. In C, the compiler can only protect you from yourself to a limited extent. Sometimes you have to be careful! But at least this keeps you from setting a trap for others in the future. – Jonathon Reinhart Jun 21 '12 at 14:36

5 Answers5

20

Wow, slow down a little bit there. First of all, I'm pretty sure programmers have been using 4-byte ints for boolean variables since the beginning of programming on x86. (There used to be no such thing as a bool datatype). And I'd venture to guess that this same typedef is in the Windows 3.1 <Windows.h>.

Second, you need to understand a bit more about the architecture. You have a 32-bit machine, which means that all of the CPU registers are 4-bytes or 32-bits wide. So for most memory accesses, it is more efficient to store and access 4-byte values than it is for a 1-byte value.

If you have four 1-byte boolean variables packed into one 4-byte chunk of memory, three of those are not DWORD (4-byte) aligned. This means the CPU / memory controller actually has to do more work to get the value.

And before you go smashing on MS for making that "wasteful" typedef. Consider this: Under the hood, most compilers (probabily) still implement the bool datatype as a 4-byte int for the same reasons I just mentioned. Try it in gcc, and take a look at the map file. I bet I am right.

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • 1
    This, the alignment issues with 1 byte are horrendous with a standard size register. – TheZ Jun 20 '12 at 23:31
  • 5
    On x86, though, it's as easy to get 1 byte as it is 4. Alignment issues come into play when you have multi-byte values. The major inefficiency is that you're reading 4 bytes when 1 will do...but either way it takes the same amount of time. – cHao Jun 21 '12 at 01:40
  • 4
    Historical argument is valid, the rest isn't. GCC produces a 1-byte bool. Loading/storing 1 byte is definitely different at the chip level and has different implications for caching, alignment, and concurrency than loading 4 bytes. – edA-qa mort-ora-y Jun 21 '12 at 03:53
13

Firstly, the type used in the system API has to be as language-independent as possible, because that API will be used by a multitude of programming languages. For this reason, any "conceptual" types that might either not exist in some languages or might be implemented differently in other languages are out of question. For example, bool fits into that category. On top of that, in a system API it is a very good idea to keep the number of interface types to a minimum. Anything that can be represented by int should be represented by int.

Secondly, your assertion about this being "a waste of memory" makes no sense whatsoever. In order to become "a waste of memory" one would have to build an aggregate data type that involves an extremely large number of BOOL elements. Windows API uses no such data types. If you built such wasteful data type in your program, it is actually your fault. Meanwhile, Windows API does not in any way force you to store your boolean values in BOOL type. You can use bytes and even bits for that purpose. In other words, BOOL is a purely interface type. Object of BOOLtype normally don't occupy any long-term memory at all, if you are using it correctly.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
3

Historically BOOL was used as an anything-not-0 = TRUE type. For example, a dialog procedure returned a BOOL, that could carry a lot of information. The signature below is from Microsoft's own documentation:

BOOL CALLBACK DlgProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) 

The signature and function result conflated several issues, so in the modern API it's instead

INT_PTR CALLBACK DialogProc(
    _In_  HWND hwndDlg,
    _In_  UINT uMsg,
    _In_  WPARAM wParam,
    _In_  LPARAM lParam
);

This newfangled declaration has to remain compatible with the old one. Which means that INT_PTR and BOOL have to be the same size. Which means that in 32-bit programming, BOOL is 32 bits.

In general, since BOOL can be any value, not just 0 and 1, it's a very ungood idea to compare a BOOL to TRUE. And even though it works to compare it against FALSE, that's generally also bad practice because it can easily give people the impression that comparing against TRUE would be OK. Also, because it's quite unnecessary.

By the way, there are more boolean types in the Windows API, in particular VARIANT_BOOL which is 16 bits and where logical TRUE is represented as the all 1 bitpattern, i.e. -1 as a signed value…

That's an additional reason why it's not a good idea to compare directly with logical FALSE or TRUE.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
2

The processor is 32 bit, and has a special flag when it operates on a zero integer, making testing for 32 bit boolean values very, very, very fast.

Testing for a 1 bit, or one byte boolean value is going to be many times slower.

If you are worried about memory space, then you might worry about 4 byte bool variables.

Most programmers, however, are more worried about performance, and thus the default is to use the faster 32 bit bool.

You might be able to get your compiler to optimize for memory usage if this bothers you.

Adam Davis
  • 91,931
  • 60
  • 264
  • 330
  • 1
    @cHao yes,but you have to do more work getting that byte from memory. You need to pull in at least 32 bits and mask it. – Adam Davis Jun 21 '12 at 03:55
  • 2
    What's more, most x86 CPUs these days -- 32 bit ones! -- have 64 bit data buses (Intel's done it since P6, i believe...maybe even the original Pentium), so that masking and/or shifting would *still* need doing. – cHao Jun 22 '12 at 07:11
0

Most of the answers in here seem to be misinformed. Using 4 bytes for a boolean value is not faster than using 1 byte. x86 architecture can read 1 byte just as fast as it can read 4, but 1 byte is less memory. One of the biggest threats to performance is memory usage. Use too much memory, and you'll have more cache misses, and you'll have a slower program. This stuff doesn't really matter if you're dealing with only a handful (hundreds!) of booleans, but if you have a ton of them, using less memory is key to higher performance. In the case of a massive array, I'd recommend 1 bit instead of 1 byte, as the extra logic to mask that bit is inconsequential if it's saving 87% of memory. You see this practice a lot with flag bitfields.

The answer for the question is most definitely just "legacy reasons." That is, "Don't touch things that aren't broken." Changing a line of code like for a minor optimization might introduce hundreds of other problems that nobody wants to deal with.

mukunda
  • 2,908
  • 15
  • 21