Strange definitions of TRUE and FALSE macros

23,122

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.

Share:
23,122

Related videos on Youtube

Keshava GN
Author by

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, 2022

Comments

  • Keshava GN
    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 and FALSE.

    • BlackDwarf
      BlackDwarf over 8 years
      I think it's just a funny way to define TRUE as 1 and FALSE as 0
    • TartanLlama
      TartanLlama over 8 years
      Note 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
      artm over 8 years
      May I know the coding book you are referencing?
    • Prasanth Kumar
      Prasanth Kumar over 8 years
      Note that there is no point to define TRUE and FALSE in C++, since you already have true and false. Nothing stops you, of course, from defining TRUE as 1, FALSE as 0 and perhaps MAYBE as 2.
    • Jon Hanna
      Jon Hanna over 8 years
      I hope that book included this as an example of bad or deliberately obscure code.
    • Lundin
      Lundin over 8 years
      I feel these could have been written in far more creative ways. How about #define FALSE "hello" <:'\xF'??''\xA':>
    • Lundin
      Lundin over 8 years
      @DanielDaranas There's no point in defining them in C either, just include stdbool.h.
    • Martin James
      Martin James over 8 years
      That is just so appallingly bad:(
    • Jabberwocky
      Jabberwocky over 8 years
      Why do people things like this ? Or was it for an obfuscated C program contest?
    • rr-
      rr- over 8 years
      Save 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
      Lundin over 8 years
      #define TRUE 0??!??! "wtf" Ok I'll stop now :)
    • TripeHound
      TripeHound over 8 years
      #define FALSE ("1"??(1??))
    • Kaiserludi
      Kaiserludi over 8 years
      @Daniel: Shouldn't one rather define MAYBE as 0.5?
    • Prasanth Kumar
      Prasanth Kumar over 8 years
      @Kaiserludi '/'/'/', but I was assuming only integer values were allowed.
    • Kaiserludi
      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
      Keith Thompson over 8 years
      Aside from the lack of parentheses, these macros are very clever. Note that "very clever" is an insult.
    • Keith Thompson
      Keith Thompson over 8 years
      @Lundin: If you're stuck using a pre-C99 implementation that doesn't support <stdbool.h>, you can use typedef enum { false, true } bool;
    • Chaim Geretz
      Chaim Geretz over 8 years
      Very funny macro. Can we have the name of the book?
    • Michael
      Michael over 8 years
      Apparently 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
      Panzercrisis over 8 years
      Why is TRUE being defined specifically as 1, instead of a more general !FALSE?
    • cubuspl42
      cubuspl42 over 8 years
      It's not more general, it's just longer.
    • Trevor Hickey
      Trevor Hickey over 8 years
      This 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
      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
      Jeremy over 8 years
      Which book? Enquiring minds want to know.
    • Lightness Races in Orbit
      Lightness Races in Orbit over 8 years
      Was it a C coding book, or a C++ coding book?
    • TMN
      TMN over 8 years
      ISTR that in C, true is !0, not 1. So these definitions are both bad and half-wrong.
    • Admin
      Admin over 8 years
      In what coding book did you see these macro definitions?
    • Keith Thompson
      Keith Thompson over 8 years
      @Panzercrisis: !FALSE is no more general than 1. Given that FALSE is 0, !FALSE is 1 by definition.
    • Keith Thompson
      Keith Thompson over 8 years
      @TMN: !0 has exactly the same value as 1. (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
      José Ernesto Lara Rodríguez over 8 years
      That's the closest I've seen to #define TRUE FALSE //Happy debugging suckers (stackoverflow.com/questions/184618/…)
    • ouah
      ouah over 8 years
      @Bradley see the answer I posted for historical information
    • trappski
      trappski about 8 years
  • Kerrek SB
    Kerrek SB over 8 years
    This has nothing to do with ASCII.
  • Fabien
    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
    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
    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
    Keith Thompson over 8 years
    @Pawel: A conforming C implementation cannot map '/' to 0. That value is reserved for the null character.
  • Paweł Załuski
    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
    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
    Alpedar over 8 years
    It 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
    Jay over 8 years
    Alpedar -- 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 multiplying TRUE by an integer.
  • Matheus208
    Matheus208 over 8 years
    You are being pedantic.
  • Zhora
    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
    Hagen von Eitzen over 8 years
    Logical negation might be implemented as notx = TRUE- x; and works fine. Except that TRUE-FALSE is -44 (assuming ASCII)
  • Keith Thompson
    Keith Thompson over 8 years
    @Matheus208: You say that like it's a bad thing.
  • Joshua Grosso Reinstate CMs
    Joshua Grosso Reinstate CMs over 8 years
    Wow. 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
    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 of int, not bool.)