TRUE和FALSE宏的奇怪定义

我曾在一本编码书中看到以下宏定义。

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

没有任何解释。

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

23495 次浏览

这只是另一种写法

#define TRUE 1
#define FALSE 0

表达式'/'/'/'将把'/'的char值除以它自己,结果是1。

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

但是整个define表达式周围的括号缺失,这可能导致使用这些宏的代码出现错误。周杰伦的回答很好地解决了这个问题。

忘记括号可能有害的“现实”场景的一个例子是将这些宏与c风格的强制转换操作符结合使用。如果有人决定在c++中将这些表达式转换为bool,例如:

#include <iostream>


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


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

以下是我们得到的结果:

True: 0
False: -44

因此,(bool) TRUE将实际计算为false,而(bool) FALSE将计算为true

它相当于写作

#define TRUE 1
#define FALSE 0

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

类似地,表达式'-'-'-'从自身减去字符-并计算为0

最好还是写下来

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

避免与其他高优先级操作符一起使用时意外更改值。

让我们看看:'/' / '/'意味着char字面值/,除以char字面值'/'本身。结果是1,这听起来对TRUE是合理的。

'-' - '-'意味着char字面量'-',从自身减去。这是0 (FALSE)。

这有两个问题:首先,它是不可读的。使用10绝对更好。此外,正如TartanLlama和KerrekSB指出的那样,如果你打算使用这个定义,请在它们周围加上括号,这样你就不会有任何惊喜:

#include <stdio.h>


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


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

这将打印char字面值'-'的值(在我的系统上是45)。

括号:

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

程序正确地输出0,尽管将真值乘以一个整数没有多大意义,但这只是一种意外错误的例子,如果您不给宏加上括号,这些错误可能会咬您一口。

让我们从“真”开始。你可以把它读成'/' / '/',意思是“字符/除以字符/”。因为在C语言中,每个字符都是一个数值(在一个字节上),它可以被读取为“字符'/'的ASCII值除以相同字符的ASCII值”,这意味着1(因为,显然,x/x是1)。因此,TRUE为1。

对于FALSE,其推理相同:'-'-'-'读取'-' - '-',即“'-'的ASCII值减去'-'的ASCII值”,即0。因此,FALSE为0。

这是对显而易见的事实的一种粗暴的表述。

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

出于历史原因,这些表达式'/'/'/''-'-'-'来自1984年第一届国际混淆C代码大赛的一个条目:

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);}

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

另外,如果我没记错的话,这些表达式作为TRUEFALSE的混淆宏也在Don Libes(1993)的《困惑的C和其他谜团》书中介绍过。

这是为TrueFalse编写宏的一种有趣的方式。

正如许多解释所提供的那样,/意味着一个1字节的数字(根据ASCII),当它被自己除法时,它会给你1,这将被视为True,同样地,-也是一个字节数,当减去相同的值时,它会给你0,这将被解释为false

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

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

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

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