Strange definitions of TRUE and FALSE macros
Solution 1
Let's see: '/' / '/'
means the char
literal /
, divided by the char
literal '/'
itself. The result is one, which sounds reasonable for TRUE
.
And '-' - '-'
means the char
literal '-'
, subtracted from itself. This is zero (FALSE
).
There are two problems with this: first, it's not readable. Using 1
and 0
is absolutely better. Also, as TartanLlama and KerrekSB have pointed out, if you are ever going to use that definition, please do add parentheses around them so you won't have any surprises:
#include <stdio.h>
#define TRUE '/'/'/'
#define FALSE '-'-'-'
int main() {
printf ("%d\n", 2 * FALSE);
return 0;
}
This will print the value of the char
literal '-'
(45 on my system).
With parentheses:
#define TRUE ('/'/'/')
#define FALSE ('-'-'-')
the program correctly prints zero, even though it doesn't make much sense to multiply a truth value by an integer, but it's just an example of the kind of unexpected bugs that could bite you if you don't parenthesize your macros.
Solution 2
It's just another way of writing
#define TRUE 1
#define FALSE 0
The expression '/'/'/'
will divide the char value of '/'
by itself, which will give 1 as a result.
The expression '-'-'-'
will substract the char value of '-'
from itself, which will give 0 as a result.
Brackets around the whole define
expressions are missing though, which can lead to errors in the code using these macros. Jay's answer adresses that pretty well.
An example of "real-life" scenario where forgetting the brackets can be harmful is the combined use of these macros with a C-style cast operator. If someone decides to cast these expressions to bool
in C++ for instance:
#include <iostream>
#define TRUE '/'/'/'
#define FALSE '-'-'-'
int main() {
std::cout << "True: " << (bool) TRUE << std::endl;
std::cout << "False: " << (bool) FALSE << std::endl;
return 0;
}
Here's what we get:
True: 0
False: -44
So (bool) TRUE
would actually evaluate to false
, and (bool) FALSE
would evaluate to true
.
Solution 3
It is equivalent to writing
#define TRUE 1
#define FALSE 0
What the expression '/'/'/'
actually does is dividing the character /
(whatever its numeric value is) by itself, so it becomes 1
.
Similarly, the expression '-'-'-'
subtracts the character -
from itself and evaluates to 0
.
It would be better to write
#define TRUE ('/'/'/')
#define FALSE ('-'-'-')
to avoid accidental change of values when used with other higher-precedence operators.
Solution 4
Jay already answered why the values of these expressions are 0
and 1
.
For history sake, these expressions '/'/'/'
and '-'-'-'
come from one of the entries of 1st International Obfuscated C Code Contest in 1984:
int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\
o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}
(Link to the program here, there is a hint of what this program does in the IOCCC page above.)
Also if I remember correctly these expressions as obfuscated macros for TRUE
and FALSE
were also covered in "Obfuscated C and Other Mysteries" book by Don Libes (1993).
Solution 5
It is a hilarious way of writing macros for True
and False
.
As many explanations have been provided /
means a 1-byte number(as per ASCII) when divided by itself it gives you 1
which will be treated as True
and likewise -
is again a byte number when subtracted the same value it gives you 0
which will be interpreted as false
#define TRUE '/'/'/'
#define FALSE '-'-'-'
hence we can replace /
or -
with any char we like, for example:
#define TRUE '!'/'!'
#define FALSE 'o'-'o'
Will keep the same meaning as the original expression.
Related videos on Youtube
Keshava GN
B.E. graduate, Senior Embedded Software developer, Have more than 6 years experience in Embedded Software development (BSP, drivers, applications, Azure IoT Edge, Docker) including Windows CE, Windows, Linux, ThreadX RTOS, UEFI, BIOS etc, living in Bengaluru, India. Currently working on Azure IoT Edge and Windows Device Drivers. Was awarded with Microsoft MVP (Most Valuable Professional) from 2016 to 2018 in Windows Development (Windows Embedded/IoT). See my 'technical' blog "Windows Embedded Compact 7" About Me : about.me/keshavagn If needed, contact me on: keshava DOT gn AT gmail DOT com MSDN Forum User Profile: Keshava @ MSDN Forum Freescale Community User Profile: Keshava @ Freescale Community LinkedIn Profile: Keshava @ LinkedIn Facebook Profile: Keshava @ Facebook Google Plus Profile: +Keshava From Sullia, D.K and now in Bangalore, India. My B.E. degree was from KVGCE, Sullia. (V.T.U). Network Profile:
Updated on July 08, 2022Comments
-
Keshava GN almost 2 years
I have seen the following macro definitions in a coding book.
#define TRUE '/'/'/' #define FALSE '-'-'-'
There was no explanation there.
Please explain to me how these will work as
TRUE
andFALSE
.-
BlackDwarf over 8 yearsI think it's just a funny way to define TRUE as 1 and FALSE as 0
-
TartanLlama over 8 yearsNote that this is a terrible idea without brackets around those expressions. I mean it's a terrible idea with them, but without you're just asking for a long night of debugging.
-
artm over 8 yearsMay I know the coding book you are referencing?
-
Prasanth Kumar over 8 yearsNote that there is no point to define TRUE and FALSE in C++, since you already have
true
andfalse
. Nothing stops you, of course, from defining TRUE as 1, FALSE as 0 and perhaps MAYBE as 2. -
Jon Hanna over 8 yearsI hope that book included this as an example of bad or deliberately obscure code.
-
Lundin over 8 yearsI feel these could have been written in far more creative ways. How about
#define FALSE "hello" <:'\xF'??''\xA':>
-
Lundin over 8 years@DanielDaranas There's no point in defining them in C either, just include stdbool.h.
-
Martin James over 8 yearsThat is just so appallingly bad:(
-
Jabberwocky over 8 yearsWhy do people things like this ? Or was it for an obfuscated C program contest?
-
rr- over 8 yearsSave for parentheses, I think it's funny. IDK what's unreadable about this, unlike Lundin's example. Obfuscated C program contest entries contain much "worse" techniques.
-
Lundin over 8 years
#define TRUE 0??!??! "wtf"
Ok I'll stop now :) -
TripeHound over 8 years
#define FALSE ("1"??(1??))
-
Kaiserludi over 8 years@Daniel: Shouldn't one rather define MAYBE as 0.5?
-
Prasanth Kumar over 8 years@Kaiserludi
'/'/'/'
, but I was assuming only integer values were allowed. -
Kaiserludi over 8 years@Daniel: Another idea would be to rand()%2 define MAYBE as rand()%2, so that is is sometimes == TRUE and sometimes == FALSE.
-
Keith Thompson over 8 yearsAside from the lack of parentheses, these macros are very clever. Note that "very clever" is an insult.
-
Keith Thompson over 8 years@Lundin: If you're stuck using a pre-C99 implementation that doesn't support
<stdbool.h>
, you can usetypedef enum { false, true } bool;
-
Chaim Geretz over 8 yearsVery funny macro. Can we have the name of the book?
-
Michael over 8 yearsApparently whoever wrote 1 and 0 that way had too much time on his hands and no consideration for how these macros were going to be used in expressions.
-
Panzercrisis over 8 yearsWhy is
TRUE
being defined specifically as1
, instead of a more general!FALSE
? -
cubuspl42 over 8 yearsIt's not more general, it's just longer.
-
Trevor Hickey over 8 yearsThis is an alternative way to define boolean values when particular keys are broken on your keyboard. For those who mention the lack of parenthesis, how would one even type ')' when they can't already type '0'?
-
Steve Jessop over 8 years@Panzercrisis: presumably because
!FALSE
is (on an ASCII system)-45
due to the afore-mentioned missing parentheses. Maybe the author tried your idea but couldn't figure out why it didn't work ;-) -
Jeremy over 8 yearsWhich book? Enquiring minds want to know.
-
Lightness Races in Orbit over 8 yearsWas it a C coding book, or a C++ coding book?
-
TMN over 8 yearsISTR that in C, true is !0, not 1. So these definitions are both bad and half-wrong.
-
Admin over 8 yearsIn what coding book did you see these macro definitions?
-
Keith Thompson over 8 years@Panzercrisis:
!FALSE
is no more general than1
. Given thatFALSE
is0
,!FALSE
is1
by definition. -
Keith Thompson over 8 years@TMN:
!0
has exactly the same value as1
. (Any non-zero value is considered "true" when used in a condition, but that's not what the!
operator means.) -
José Ernesto Lara Rodríguez over 8 yearsThat's the closest I've seen to
#define TRUE FALSE //Happy debugging suckers
(stackoverflow.com/questions/184618/…) -
ouah over 8 years@Bradley see the answer I posted for historical information
-
trappski about 8 yearsBut where is FileNotFound? thedailywtf.com/articles/What_Is_Truth_0x3f_
-
-
Kerrek SB over 8 yearsThis has nothing to do with ASCII.
-
Fabien over 8 years@KerrekSB, in practice, yes, it does, unless you happen to develop on a very specific architecture, which is probably not relevant to OP's question.
-
Keith Thompson over 8 years@Fabien: It doesn't depend on ASCII.
'/'/'/'
is 1 for any valid character set, whether'/' == 47
(as it is in ASCII), or'/' == 97
(as it is in EBCDIC), or any other value. -
Paweł Załuski over 8 years@KeithThompson Well, not for any character set - just the limited subset of those that do not map
'/' == 0
;) which ASCII (or EBCDIC for that matter) are good examples of... -
Keith Thompson over 8 years@Pawel: A conforming C implementation cannot map
'/'
to0
. That value is reserved for the null character. -
Paweł Załuski over 8 years@KeithThompson :) If we're talking about ISO C then true - it defines null character as the zero byte, but still - you argued any character set and nothing stops an arbitrary character set to designate null character as the visual glyph
'/'
-
Keith Thompson over 8 years@Pawel: Sure, I could have been more explicit. But since the question is about C (and C++), that's what I meant by "any valid character set".
-
Alpedar over 8 yearsIt actually make sense to multiply with truth value. For examle indentation*should_indent will result in either 0 or indentation based on whether should_indent without branching. (I guess that this is bad example, when working with text single branching does not matter, (I've seen this technique in shaders and in XPATH (both too different and i don't remeber exact form))
-
Jay over 8 yearsAlpedar -- but it doesn't conceptually and matehmatically make senso to do so -- in this case it would be clearer (and conceptually make sense) to use an
if
instead of multiplyingTRUE
by an integer. -
Matheus208 over 8 yearsYou are being pedantic.
-
Zhora over 8 years@Matheus208 If Pawel was being pedantic, then that's ('-'-'-') since his point was based on an unstated condition; describing Keith's remarks as pedantic might be more ('/'/'/') but I'd call them "clarifying" (and with the added smileys "pedantic" definitely seems '/'-'/' to me). It may be ('-'/'-') that the comments taken together can be called pedantic but, 1) isn't that somewhat obligatory in this field? 2) they made me think; and 3) I'm a bit clearer on some things than I was. And yes, I guess I'm being pedantic myself! (But I'm clearer about what "pedantic" means than I was! ;-)
-
Hagen von Eitzen over 8 yearsLogical negation might be implemented as
notx = TRUE- x;
and works fine. Except thatTRUE-FALSE
is -44 (assuming ASCII) -
Keith Thompson over 8 years@Matheus208: You say that like it's a bad thing.
-
Joshua Grosso Reinstate CMs over 8 yearsWow. This is so wonderful. @zhora, kudos for discussing the definition of "pedantic." I give all of you my deepest congratulations for your inerrant toils to improve the accuracy of the Internet.
-
Peter Cordes almost 5 years@MarcWittke: Well, people who abuse the C preprocessor with broken macros like these will soon be without friends. It's well known that simple text substitution of things that aren't rigorously guarded with parens can create extremely non-obvious breakage, which is why C++ introduces so many ways to do things without the C preprocessor, like templates and
static const bool TRUE = true;
. (Although this definition actually has a type ofint
, notbool
.)