• (nodebb)

    Hmm, well I'm not going to put money on it, but C11 defines _Bool to be big enough to contain 0 and 1 which suggests that, if the function returns a _Bool there are, indeed, only two possible values for the switch.

  • LCrawford (unregistered)

    The critical safety system programmer should have had explicit handling of the FILE_NOT_FOUND. Or was it a homebrew boolean whose frist bool definition was true = !false?

  • Industrial Automation Engineer (unregistered)

    TRWTF is to implement a safety critical system in anything other than a safety relay / safety PLC. You know, in a language / sub-system that only supports 16-bits integer arithmetic, and if you don't evaluate the overflow-bit immediately after performing an addition, your code won't even compile. (I'm looking at you, Siemens!)

  • MaxiTB (unregistered)

    C defines boolean values as FALSE = (int)0 and TRUE = !FALSE. It's important that it is not defined as TRUE = ~FALSE, because any other integer value than zero is considered TRUE.

    And yes, I'm using uppercase on purpose, for a long time TRUE and FALSE where both just defined as marcos; C didn't had any keywords for true and false. Obviously this was not an issue, as long as you are aware of this fact and it also allowed for easy checks for return codes, which often returned 0 (so false) for OK.

  • (nodebb) in reply to Jeremy Pereira

    "Capable of holding 0 or 1" does NOT mean incapable of holding other values, simply that such things are UB and flaming nasal demons are to be considered.

  • Anonymous') OR 1=1; DROP TABLE wtf; -- (unregistered) in reply to Jeremy Pereira

    If we're being pedantic here: C11 (and C99 before it) only require _Bool to be at least large enough to hold 0 and 1. It can't be larger than unsigned char per the integer conversion ranks, so in practice it's exactly 1 byte.

    Per Boolean type, values that are converted to _Bool get set to either 0 or 1, but it's possible to work around this with e.g. memcpy() or similar operations that convert it to a character. And then even if you do that to write in any other value in the 2-255 range, when you convert back from _Bool to int, you still likely end up with 0 or 1 again depending on the compiler implementation (tested with Apple Clang 14.0.0). Only if you additionally memcpy() back out (or equivalent) can you confirm that yes, a _Bool can in fact store larger values like 2-255.

    (But please don't ever do this in production code!)

  • Long Time Lurker (unregistered) in reply to Anonymous') OR 1=1; DROP TABLE wtf; --

    re: "If we're being pedantic here"

    Of course we are, why else are we here? ;-)

  • MaxiTB (unregistered) in reply to Anonymous') OR 1=1; DROP TABLE wtf; --

    Yeah, you have to be really careful because in the part due to performance reasons some compilers used even int for bool in the past, because obviously it's way faster. 8-bit operations on modern architecture are most of the times slower than 32-bit or 64-bit operations, so for everything but storage it makes sense to use int over unsigned char. So beside of memcpy being a bad idea in the first place, you would also need to use sizeof() just to be sure and then hope that the compiler doesn't do magic expansion/compaction tricks. Ok, just lets say it's a bad bad idea :-)

  • (nodebb)

    please dont forget those lovely signed one bit integers

    struct { int frist : 1; unsigned int skond : 1; } x;

    x.frist has the value -1 and 0 .... x.skond has the value 0 and 1...

    Just try reading these bitfields from a microcontroller and e.g. multiplying them by integer constants for a bit of a mind game.

  • A. N. Ominous (unregistered)

    The default case in this snippet is likely the result of a compiler warning.

    gcc -Wall turns on a lot of warnings automatically, and is more or less standard for compiling commercially-developed code. One thing it turns on is -Wswitch, which will generate a warning for a switch/case statement if all the possible enumerations are not provided case blocks. Adding a default case prevents this warning.

    What most likely happened here: the coder wrote the getBool() function to return either 0 (false) or true (1), with no other possible returns. The switch statement was coded assuming that - but there's no way to tell the compiler that it can only return 0 or 1. Compiler treats bool as an integer and complains because there are lots of un-cased enumeration values. So the coder added the emty default statement to prevent the warning.

    The default case body should therefore be:

    // shuts idiot compiler up

  • JP (unregistered) in reply to Anonymous') OR 1=1; DROP TABLE wtf; --
    Comment held for moderation.
  • BOFH (unregistered)

    code smell to see this swifch

    Old witches swiffer that emits familiar smell of ritten code.

  • billdehaan (github)

    I once inherited a Pascal app that had been ported from Basic.

    The original Basic coder had actually tried to add some typing. Although the Basic only had the Integer and string types, he'd defined constants like int FALSE=0 and int TRUE=1, and any functions that started with "is" or "has" returned a boolean. So, "addition(x,y,z)" was an integer function that returned an integer, while "isValidInput(input)" or "hasAdminPriviledge(userId)" were both technically integer functions, but would only return integer values of FALSE(0) or TRUE(1).

    Unfortunately, the Pascal coder clearly didn't understand booleans, or types in general, so he was flummoxed when he tried to port lines from the Basic code, such as "if (isValidInput(input) == TRUE)". It would generate a syntax fault, because isValidInput() was integer, and TRUE and FALSE were predefined as booleans in Pascal.

    So, he did the only logical thing he could think of.

    He defined integer values YES=1 and NO=0, so the code could be converted to "if (isValidInput(input) == YES)".

    I fear to think what he might do with C, C++, or C# type languages.

  • a cow (maybe a robot-cow?) (unregistered) in reply to A. N. Ominous

    No, it sould have been a simpler if(getBool()) do_something_else(); else do_something();

    (Sorry for the too many elses, but I maintained the "names of the functions" ;-)

  • A. N. Ominous (unregistered) in reply to a cow (maybe a robot-cow?)

    Well, if we're going for simplicity, the most simple approach in this context would be:

    // yes, I like ternary operators. getBool() ? do_true_case_work() : do_everything_else_case_work();

    But my point really was the reason for the presence of the default case. The reasoning I gave also applies for general enumerated types where there are more than two named values; the gcc -Wall option will still cause the compiler to complain if there's no default case. It's not actually possible to reach the default, assuming the getX() function can only return values defined within the enumerated type - but the compiler does not know that and complains about the missing default.

  • Gnasher729 (unregistered) in reply to A. N. Ominous
    Comment held for moderation.

Leave a comment on “Switching to Booleans”

Log In or post as a guest

Replying to comment #:

« Return to Article