306

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.

Keshava GN
  • 4,195
  • 2
  • 36
  • 47

6 Answers6

382

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.

Jay
  • 9,585
  • 6
  • 49
  • 72
  • 8
    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)) – Alpedar Dec 04 '15 at 09:02
  • 2
    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. – Jay Dec 04 '15 at 10:26
  • 2
    Logical negation might be implemented as `notx = TRUE- x;` and works fine. Except that `TRUE-FALSE` is -44 (assuming ASCII) – Hagen von Eitzen Dec 05 '15 at 09:43
  • @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`.) – Peter Cordes May 30 '19 at 11:22
90

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.

Community
  • 1
  • 1
BlackDwarf
  • 2,070
  • 1
  • 17
  • 22
44

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.

davejal
  • 6,009
  • 10
  • 39
  • 82
Sufian Latif
  • 13,086
  • 3
  • 33
  • 70
35

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).

Community
  • 1
  • 1
ouah
  • 142,963
  • 15
  • 272
  • 331
8

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.

anand
  • 1,506
  • 14
  • 28
6

Let's start with true. You can read it as '/' / '/', which means "character '/' divided by character '/'". Since each character, in C, is a numeric value (on one byte), it can be read as "the ASCII value of character '/' divided by the ASCII value of that same character", which means 1 (because, obviously, x/x is 1). Hence, TRUE is 1.

For FALSE, its the same reasoning: '-'-'-' reads '-' - '-', i.e "the ASCII value of '-' minus the ASCII value of '-'", which is 0. Hence, FALSE is 0.

This is a nasty way to state the obvious.

Fabien
  • 12,486
  • 9
  • 44
  • 62
  • 7
    This has nothing to do with ASCII. – Kerrek SB Dec 03 '15 at 09:51
  • 1
    @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. – Fabien Dec 03 '15 at 10:01
  • 8
    @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. – Keith Thompson Dec 03 '15 at 16:24
  • @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... – Paweł Załuski Dec 03 '15 at 20:32
  • 6
    @Pawel: A conforming C implementation cannot map `'/'` to `0`. That value is reserved for the null character. – Keith Thompson Dec 03 '15 at 20:44
  • @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 `'/'` – Paweł Załuski Dec 03 '15 at 21:54
  • 2
    @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". – Keith Thompson Dec 03 '15 at 22:04
  • 2
    You are being pedantic. – Matheus208 Dec 04 '15 at 13:50
  • 4
    @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! ;-) – Zhora Dec 04 '15 at 20:31
  • 3
    @Matheus208: You say that like it's a bad thing. – Keith Thompson Dec 09 '15 at 00:32
  • 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. – Joshua Grosso Reinstate CMs Dec 09 '15 at 16:00