关于c ++:TRUE和FALSE宏的奇怪定义

Strange definitions of TRUE and FALSE macros

我在一本编码手册中看到了以下宏定义。

1
2
#define TRUE  '/'/'/'
#define FALSE '-'-'-'

那里没有解释。

请向我解释这些将如何作为TRUEFALSE工作。


让我们看看:'/' / '/'是指char/除以char'/'本身。结果是一个,这听起来对true是合理的。

'-' - '-'是指char字的'-'从自身减去。这是零(false)。

这有两个问题:第一,它不可读。使用10绝对更好。此外,正如塔坦拉玛和克里克布所指出的,如果你要使用这个定义,请在它们周围加上括号,这样你就不会有任何意外:

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

#define TRUE  '/'/'/'
#define FALSE '-'-'-'

int main() {
        printf ("%d
"
, 2 * FALSE);
        return 0;
}

这将打印char文本'-'的值(在我的系统上为45)。

带括号:

1
2
#define TRUE  ('/'/'/')
#define FALSE ('-'-'-')

程序正确地打印零,即使用一个整数乘以一个真值没有多大意义,但它只是一个意外错误的例子,如果你不用括号括起来,它可能会咬你。


这只是另一种写作方式

1
2
#define TRUE 1
#define FALSE 0

表达式'/'/'/'将把'/'的char值本身除以,得到1。

表达式'-'-'-'将从自身减去'-'的char值,结果将得到0。

但是,整个define表达式周围的括号丢失,这可能导致使用这些宏的代码出错。杰伊的回答很好。

"现实生活"场景中,忘记括号可能有害的一个例子是将这些宏与C样式的强制转换运算符结合使用。如果有人决定在C++中将这些表达式转换为EDCOX1 5Ω,例如:

1
2
3
4
5
6
7
8
9
10
#include <iostream>

#define TRUE  '/'/'/'
#define FALSE '-'-'-'

int main() {
    std::cout <<"True:" << (bool) TRUE << std::endl;
    std::cout <<"False:" << (bool) FALSE << std::endl;
    return 0;
}

我们得到的是:

1
2
True: 0
False: -44

因此,(bool) TRUE将对false进行实际评估,(bool) FALSE将对true进行评估。


它相当于写作

1
2
#define TRUE 1
#define FALSE 0

表达式'/'/'/'实际做的是将字符/(无论其数值是什么)本身除以它本身,因此它成为1

同样,表达式'-'-'-'从自身减去字符-,并计算为0

最好是写

1
2
#define TRUE ('/'/'/')
#define FALSE ('-'-'-')

以避免与其他更高优先级的运算符一起使用时意外更改值。


Jay已经回答了为什么这些表达式的值是01

为了历史起见,这些表达"EDOCX1"〔0〕和"EDOCX1"〔2〕来自1984年第一届国际模糊C码比赛的参赛作品之一:

1
2
3
int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\
o, world!
"
,'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}

(链接到这里的程序,在上面的ioccc页面中有这个程序所做的提示。)

另外,如果我能正确地记住,这些表达式是用于truefalse的模糊宏,那么这些表达式也包含在don libes(1993)的《模糊C和其他奥秘》一书中。


truefalse编写宏的方式很滑稽。

正如所提供的许多解释一样,/表示一个1字节数(按ASCII),当它本身被除时,它给你一个1,它将被视为true,同样,-在减去它给你的相同值时,它也同样是一个字节数,它给你一个0,它将被解释为false

1
2
#define TRUE  '/'/'/'
#define FALSE '-'-'-'

因此,我们可以用我们喜欢的任何字符来替换/-,例如:

1
2
#define TRUE  '!'/'!'
#define FALSE 'o'-'o'

将保持与原始表达式相同的含义。


让我们从"真"开始。你可以把它读作'/' / '/',意思是"字符'/'除以字符'/'"。因为C中的每个字符都是一个数值(在一个字节上),所以可以将其读作"字符'/'的ASCII值除以同一字符的ASCII值",这意味着1(显然,X/X是1)。因此,true为1。

对于false来说,其推理是一样的:'-'-'-'读取'-' - '-',即‘-’的ASCII值减去‘-’的ASCII值,即0。因此,false为0。

这是一种令人讨厌的表达显而易见的事情的方式。