• LCrawford (unregistered)

    Of course FILE_NOT_FOUND is a boolean value - it's true whenever a file is not found.

  • Me (unregistered) in reply to LCrawford

    Woooosh!!!!

  • (nodebb)

    My guess this file was written by somebody used to Java or another similar language who did not bother reading all the relevant details in the documentation. The C version of

    final
    is
    const
    , not
    static
    .

    Addendum 2020-07-07 07:01: Oops, that last sentence was supposed to be: The C version of "final" is "const", not "static".

  • Dave (unregistered)

    Was the code written by Trump's press secretary?

  • (nodebb)

    PoMo programming rules! What it rules depends on its semiotics.

  • Dnrb (unregistered)

    I would love to insert this line in the application: if((true-= 1) == false) false += 1;

  • Naomi (unregistered) in reply to Nutster

    In Java, unlike C, static has exactly one meaning - "this member is a member of the class, not per instance of the class" - and since Java's version of a namespace is a utility class¹, one place it sees frequent use is declaring global constants². So, our developer probably threw static on there by analogy to how it's used in Java, not realizing it means something totally different in C; they clearly didn't bother to look up const, so why would they verify any of their other assumptions?


    ¹ Sometimes framed as "Java forces OOP everywhere!", which anyone arguing in good faith can tell you is patently absurd. It's object-oriented by default and has the static keyword for when that's not what you want.

    ² Well, not exactly "global" since you need to import the class, but you know what I mean. Using static for global variables is almost as horrid as talking at the theatre.

  • Sole Purpose Of Visit (unregistered)

    Uuuummmm … the actual WTF here is:

    typedef int bool
    

    Unless, of course, you want to allow for future universes where Booleans are somehow not Booleans. I mean, UNIVERSE_NOT_FOUND or something like that.

    I wouldn't recommend using static rather than const in C of any flavour, but the distinction is a bit of a "meh" when it comes to true/false. If one of your programmers wants to redefine true and false, then you have a legitimate reason to fire them on the spot. No jury would convict you. I doubt it ever happens …

    … except with PL/1, where you can literally redefine any keyword you like. I've never been sure about the scoping of such redefinitions, but in all honesty reducing the scope of a keyword definition is probably even worse than the original concept.

  • Sole Purpose Of Visit (unregistered) in reply to Sole Purpose Of Visit

    I should probably expand on that. (Sorry! TL;DR.)

    int is a stupid choice. (Actually, bool is a stupid name, because you can reasonably assume in 1990 that the next version of C will use the keyword bool. Back then we used BOOL.)

    If you really have to do this (say on an embedded system that somehow hasn't caught up to Prince and doesn't party like it's 1999), then at least use an unsigned type, as short as you can manage. I can't really imagine that anybody would misuse unsigned char under the circs.

    But there's always a bigger idiot, so perhaps my imagination is too limited. Well then, limit the semantics even further:

    typedef enum { false = 0, true = !false } BOOL;
    

    From memory, that works in all K&R/ANSI/C89 cases. Also going forward, because you can always redefine BOOL.

  • Blarg (unregistered) in reply to Sole Purpose Of Visit

    Sure, but using BOOL doesn't help you if you have an existing C code base from another platform and you're trying to get it to build in Visual Studio. ... unless you feel like doing a search and replace on the whole code base. Seems like adding your own stdbool header file would be easier. Not that this is a GOOD stdbool header, but they had the right idea.

  • Tim (unregistered)

    TRWTF is, of course, the C language, on account of (a) not having a boolean type in the first place, and (b) using the keyword "static" to mean something unintuitive

  • qwerqwerqwer (unregistered)

    TRWTF is, of course, Microsoft Visual C++ not including stdbool.h until VC2013. I haven't had to use MSVC for a while, but I assume that even ten years later, it supports only a minimal subset of C99.

  • FILE_NOT_FOUND (unregistered) in reply to Sole Purpose Of Visit

    'bool' isn't a stupid choice here because they're polyfilling the actual bool in later versions of the language.

  • Simon Clarkstone (unregistered)

    "you can reasonably assume in 1990 that the next version of C will use the keyword bool"

    To be pedantic, the committee ended up creating the keyword "_Bool", with "bool" as a macro.


    "static" isn't completely terrible here, as it (roughly) makes the variable have the scope of one file and not be visible to the linker, which means that the optimiser has a good chance of statically deducing that "true" and "false" are never assigned to (nor have a reference taken) and therefore inlining them.

  • Sole Purpose Of Visit (unregistered) in reply to Blarg

    Considering that your alternative of importing an external code base from C99 (with bool) to C89 (without bool) involves completely changing the semantics of a C99 bool to a C89 signed int -- which may or may not have been the motivating problem behind today's WTF -- I think I'd rather just sed through the external code base, thanks.

    Or, better still, use a proper C macro definition (such as my -- borrowed -- example of an enum) and just go and fix things where they don't compile.

    At least that way you've fixed things in advance, rather than watch them blow up at random points in the future. Which latter I spent 20 years of my C programming life doing.

  • Sole Purpose Of Visit (unregistered) in reply to FILE_NOT_FOUND

    By changing the semantics to a signed integer of platform-dependent length?

    I think not. It's cretinous,.

  • Sole Purpose Of Visit (unregistered) in reply to Tim

    The interesting thing here is that K&R did have the concept of bool, what with having an extensive set of Boolean operators. (Some of which didn't quite have an intuitive precedence, but there you are.) Mostly that concept was embedded in return values, and Brian and Ken may not necessarily have picked the right value of true and false … what with 0 being the more or less universal signifier that the called function -- C or shell -- succeeded.

    It's an inherited feature from either B or BCPL, I'm never quite sure. I quite like 0 as "success" and anything else as "failure", because that leaves a lot of lexical scope for different failures. And you don't need any lexical scope for success.

    Unfortunately, success and failure do not necessarily map perfectly onto truth and falsitude.

    Then again, no sane person would claim that a Boolean of any sort whatsoever (including FILE_NOT_FOUND) maps onto a signed integer.

    I mean, how do you reason about that? How does even a [B]compiler[/B}, let alone a [B}linker[/B}, reason about that?

  • sizer99 (google) in reply to Dave

    If it was Trump's press secretary (any of them) you'd have

    static bool true = 0;

    static bool false = INFINITY;

  • (nodebb) in reply to Sole Purpose Of Visit

    "you don't need any lexical scope for success"

    That's an awfully bold statement that I don't think is supportable.

  • Sole Purpose Of Visit (unregistered) in reply to Sulis

    Possibly not.

    What, then, would you consider "partial success" to be?

    And how would you suggest that a compiler, or a linker, or even a future programmer, approach the interesting epistemological question of what to do with partial success?

    It might be possible, with enough effort. But I think I'd prefer "success" to map to what you'd expect in each and every case. Which is to say, "it did exactly and precisely what I wanted it to do."

    (Not quite the same as true or false, I will agree.)

    But we're drifting away from the original WTF. There is no, and I mean no, I say no, call me Foghorn Leghorn if you want, pay attention to me son, NO justification for widening the semantics of a bool to a signed integer. JUST USE AN ENUM.

    Then again, you could use Rust's return dual of a "success/failure"/"value" if you need more semantic information … but I think I'm drifting off-subject here. Rust has sane macros, as opposed to C's insane macros (and typedefs). But that's not really the point at issue. If you have to use C, or VB, or PHP, or BrainF*ck for all I care -- don't piss around. To paraphrase Einstein (an invented quote, apparently):

    Make it as simple/obvious/intelligible/constrained as you can possibly make it. But no more.

  • Pavilon (unregistered) in reply to Sole Purpose Of Visit

    Can you give an example?

  • King (unregistered)

    I am really impressed by all the long and often competent comments here. I am only capable of writing mediocre one liners. Maybe one day my prefrontal cortex will impress me and show it has competence too?

  • Sole Purpose Of Visit (unregistered) in reply to King

    It already has.

  • qwerqwerqwer (unregistered) in reply to Sole Purpose Of Visit

    The underlying representation of a C99 _Bool is implementation-defined anyway. It's only an issue if you're linking against code that uses another definition.

  • Edd (unregistered)

    Nice to see someone anticipating programs with a million different definitions of true and false, although the ones writing them won't figure out how to include today's header file.

  • (nodebb) in reply to Sole Purpose Of Visit

    I quite like 0 as "success" and anything else as "failure", because that leaves a lot of lexical scope for different failures. And you don't need any lexical scope for success.

    S_FALSE is knocking on your door, asking about what you said about success.

    For those in the audience who've never heard of this abomination, well, lucky you. It's an HRESULT that certain COM calls can return, and as you can see, it's tagged S_ at the beginning, so it indicates success.

    Its value? So glad you asked. S_FALSE == 1. A plain unadorned success is S_OK which is zero, so S_FALSE indicates some sort of nuance of success.

  • Hammy (unregistered)

    By defining your own bool for a system that lacks it you can introduce bugs since the _Bool type always will be either 0 or 1. Thus it would be legal (but strange, I admit) to write something like somebool == true which will be perfectly fine with standard C, but not work with the home made one.

  • FILE_NOT_FOUND (unregistered) in reply to Sole Purpose Of Visit

    By changing the semantics to a signed integer of platform-dependent length? I'm not arguing about whether typedeffing it to 'int' is stupid - I'm not a low level enough person to know what the appropriate polyfill actually is (though, in reality, any numeric type will work fine for 99% of cases).

    It looks from a cursory search as if it's not actually defined what the underlying type is. I would expect 'byte' (or 'unsigned char' which I think is how 'byte' is defined?) rather than 'int'. But 'char' is 'of platform-dependent length' anyway, isn't it?

  • (nodebb)

    They should have used at least float for boolean values: true = one-ish false = zero-ish

  • DanK (unregistered) in reply to FILE_NOT_FOUND

    sizeof(char) is 1. Everything else is measured relative to char. The range of char can change with the implementation, however. This is to support architectures where the memory is not byte-addressable. A lot of applications that define their own 'bool' type use a 32b integer. On some machines, this could have a performance advantage if the instruction set is better suited for operating on words. I would expect sizeof(_Bool) to follow what is defined in the ABI or to be defined based on the instruction set of the machine. Either way, you should not mix definitions of 'bool' in one program. You will shoot yourself in the foot.

  • A counter-argument (unregistered)

    Someone, somewhere, thinks we need more than 0 lexical space for success.

    https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_Success

    re: the wtf If they had used "static const" it would have been fine. If they had used "#define false 0" and "#define true (!false)" it would have been fine. As it is, it's not fine. An enum would have been best, but I don't think it qualifies for WTF status solely because they used an implementation-defined signed type that's at least big enough to hold true and false.

    As for true and false being data in .bss, I'm not sure what kind of monster takes the address of true, but a really evil person could pass &true into some function that modifies its arguments.

  • Ugh (unregistered) in reply to DanK

    You just reminded me of a system I worked on where "char" was 16 bits and the faux-C99 headers typedef'd uint8_t to an unsigned char. That led to some interesting bugs.

  • markm (unregistered)

    Defining "true" and "false" as static means that they can be changed in a function - and the change will persist when the program exits the function, then calls it again. Unless you define them with "const", the following code is legal and guaranteed to lead to baffling bugs:

    true = 1; if(x = true) ... true = 0; if(y = true)...

    And "static" in C is quite intuitive to me. It means the opposite of dynamic (AKA automatic), which are the usual sort of local variables that are created each time a function is called, and destroyed when it returns (usually implemented on the stack, or sometimes only as a register). Inside a function, it defines a variable that is persistent between calls to the function; it's probably placed with the global variables, but the name is hidden from other functions.

    It's not so intuitive when applied to a global variable (in c, that means any variable defined outside of a function). Global variables are already static, so "static" here has to mean something else, or be meaningless...

  • DanK (unregistered) in reply to markm

    Global variables are not static. In this context, "static" means that the variable or function is local to the compilation unit. The symbol will not show up in the resulting object file, so you can reuse the name between modules. So, in this case, each compilation unit that includes this header will get its own true and false variables.

    (Technically, when "static" is used in a function, it has the same meaning to the compiler, but the developer has a very different intent.)

  • Have you tried turning it off, and then on again? (unregistered) in reply to Naomi

    "In Java, unlike C, static has exactly one meaning - "this member is a member of the class, not per instance of the class" - and since Java's version of a namespace is a utility class¹, one place it sees frequent use is declaring global constants². So, our developer probably threw static on there by analogy to how it's used in Java, not realizing it means something totally different in C; they clearly didn't bother to look up const, so why would they verify any of their other assumptions?"

    Not at all. Static actually has several me4anings in C, none of them has to do with classes (since C does not actually have classes), you can change storage duration from auto to static, and you can change linkage from external to internal, e.g.

    int foo; // static storage duration, external linkage static int bar; // static storage duration, internal linkage

    void snafu() { int a; // auto storage duration, no linkage static int b; // static storage duration, no linkage }

Leave a comment on “Your Personal Truth”

Log In or post as a guest

Replying to comment #515946:

« Return to Article