- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Of course FILE_NOT_FOUND is a boolean value - it's true whenever a file is not found.
Admin
Woooosh!!!!
Admin
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
is , not .Addendum 2020-07-07 07:01: Oops, that last sentence was supposed to be: The C version of "final" is "const", not "static".
Admin
Was the code written by Trump's press secretary?
Admin
PoMo programming rules! What it rules depends on its semiotics.
Admin
I would love to insert this line in the application: if((true-= 1) == false) false += 1;
Admin
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 threwstatic
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 upconst
, 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.Admin
Uuuummmm … the actual WTF here is:
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.
Admin
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:
From memory, that works in all K&R/ANSI/C89 cases. Also going forward, because you can always redefine BOOL.
Admin
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.
Admin
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
Admin
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.
Admin
'bool' isn't a stupid choice here because they're polyfilling the actual bool in later versions of the language.
Admin
"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.
Admin
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.
Admin
By changing the semantics to a signed integer of platform-dependent length?
I think not. It's cretinous,.
Admin
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?
Admin
If it was Trump's press secretary (any of them) you'd have
static bool true = 0;
static bool false = INFINITY;
Admin
"you don't need any lexical scope for success"
That's an awfully bold statement that I don't think is supportable.
Admin
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.
Admin
Can you give an example?
Admin
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?
Admin
It already has.
Admin
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.
Admin
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.
Admin
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 taggedS_
at the beginning, so it indicates success.Its value? So glad you asked.
S_FALSE == 1
. A plain unadorned success isS_OK
which is zero, soS_FALSE
indicates some sort of nuance of success.Admin
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.
Admin
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?
Admin
They should have used at least float for boolean values: true = one-ish false = zero-ish
Admin
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.
Admin
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.
Admin
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.
Admin
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...
Admin
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.)
Admin
"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 }