奇怪的TRUE和FALSEmacros的定义
我在一本编码书中看到了下面的macros定义。
#define TRUE '/'/'/' #define FALSE '-'-'-'
那里没有解释。
请向我解释这些将如何工作为TRUE
和FALSE
。
让我们来看看: '/' / '/'
是指char
字面量/
除以char
'/'
本身。 结果是一个,这对TRUE
听起来是合理的。
而'-' - '-'
表示char
'-'
,从自身中减去。 这是零( FALSE
)。
有两个问题:首先,它不可读。 使用1
和0
是绝对更好的。 另外,正如TartanLlama和KerrekSB指出的那样,如果你打算使用这个定义,请在它们周围添加圆括号,这样你就不会有任何的惊喜:
#include <stdio.h> #define TRUE '/'/'/' #define FALSE '-'-'-' int main() { printf ("%d\n", 2 * FALSE); return 0; }
这将打印char
'-'
(在我的系统上是45)的值。
括号:
#define TRUE ('/'/'/') #define FALSE ('-'-'-')
程序正确地打印零,即使把一个真值乘以一个整数没有太大的意义,但这只是一个例子,如果你不用括号括起来的话,这种意外的错误会咬你。
这只是另一种写作方式
#define TRUE 1 #define FALSE 0
expression式'/'/'/'
将会自行分割'/'/'/'
的char值,结果为1。
expression式'-'-'-'
将减去'-'
的char值,从而得到0。
整个define
expression式的括号都丢失了,这会导致代码中使用这些macros的错误。 周杰伦的回答非常好。
忘记括号的“现实生活”情况的一个例子是将这些macros与C风格的演员操作符结合使用。 如果有人决定在C ++中将这些expression式转换为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
'/'/'/'
这个expression式实际上是把字符/
(不pipe它的数值是什么)除以它自己,所以它变成1
。
类似地,expression式'-'-'-'
从自身中减去字符并评估为0
。
写作会更好
#define TRUE ('/'/'/') #define FALSE ('-'-'-')
以避免与其他更高优先级的操作符一起使用时发生意外的值更改。
周杰伦已经回答了为什么这些expression式的值是0
和1
。
为了历史的缘故,这些expression式'/'/'/'
和'-'-'-'
来自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页面中有一些提示。)
另外,如果我没有记错,这些expression式作为TRUE
和FALSE
混淆macros也被Don Libes(1993)的“混淆的C和其他未解之谜”一书所涵盖。
我们从真实开始。 你可以把它看作'/' / '/'
,意思是“字符”/“字符分隔”/“”。 由于C中的每个字符都是一个数字值(在一个字节上),因此它可以被读为“字符的ASCII值”/“除以相同字符的ASCII值”,这意味着1(因为显然, x / x是1)。 因此, TRUE
是1。
对于FALSE
,其原因相同: '-'-'-'
读取'-' - '-'
,即“ASCII值 – '减去' – '”的ASCII值,即0。因此, FALSE
是0。
这是一个讨厌的方式来陈述明显的。
编写True
和False
macros的方式很有趣。
由于许多解释已经提供/
意味着一个1字节的数字(按照ASCII)分开时它给你1
将被视为True
,同样-
再次是一个字节数减去相同的价值,它给你0
被解释为false
#define TRUE '/'/'/' #define FALSE '-'-'-'
因此我们可以用任何我们喜欢的字符replace/
或者-
例如:
#define TRUE '!'/'!' #define FALSE 'o'-'o'
将保持原来的expression意义相同。