There was a similar question here, but the user in that question seemed to have a much larger array, or vector. If I have:
bool boolArray[4];
And I want to check if all elements are false, I can check [ 0 ], [ 1 ] , [ 2 ] and [ 3 ] either separately, or I can loop through it. Since (as far as I know) false should have value 0 and anything other than 0 is true, I thought about simply doing:
if ( *(int*) boolArray) { }
This works, but I realize that it relies on bool being one byte and int being four bytes. If I cast to (std::uint32_t) would it be OK, or is it still a bad idea? I just happen to have 3 or 4 bools in an array and was wondering if this is safe, and if not if there is a better way to do it.
Also, in the case I end up with more than 4 bools but less than 8 can I do the same thing with a std::uint64_t or unsigned long long or something?
As πάντα ῥεῖ noticed in comments, std::bitset
is probably the best way to deal with that in UB-free manner.
std::bitset<4> boolArray {}; if(boolArray.any()) { //do the thing }
If you want to stick to arrays, you could use std::any_of
, but this requires (possibly peculiar to the readers) usage of functor which just returns its argument:
bool boolArray[4]; if(std::any_of(std::begin(boolArray), std::end(boolArray), [](bool b){return b;}) { //do the thing }
Type-punning 4 bool
s to int
might be a bad idea - you cannot be sure of the size of each of the types. It probably will work on most architectures, but std::bitset
is guaranteed to work everywhere, under any circumstances.
Several answers have already explained good alternatives, particularly std::bitset
and std::any_of()
. I am writing separately to point out that, unless you know something we don't, it is not safe to type pun between bool
and int
in this fashion, for several reasons:
int
might not be four bytes, as multiple answers have pointed out.bool
might not be one byte. I'm not aware of any real-world architectures in which this has ever been the case, but it is nevertheless spec-legal. It (probably) can't be smaller than a byte unless the compiler is doing some very elaborate hide-the-ball chicanery with its memory model, and a multi-byte bool seems rather useless. Note however that a byte need not be 8 bits in the first place.int
can have trap representations. That is, it is legal for certain bit patterns to cause undefined behavior when they are cast to int
. This is rare on modern architectures, but might arise on (for example) ia64, or any system with signed zeros.You should use one of the alternative solutions provided by the other answers.
* It is legal (with some qualifications, particularly regarding alignment) to reuse the memory pointed to by boolArray
by casting it to int and storing an integer, although if you actually want to do this, you must then pass boolArray
through std::launder
if you want to read the resulting int later. Regardless, the compiler is entitled to assume that you have done this once it sees the read, even if you don't call launder.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With