奇怪的TRUE和FALSEmacros的定义

我在一本编码书中看到了下面的macros定义。

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

那里没有解释。

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

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

'-' - '-'表示char '-' ,从自身中减去。 这是零( 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 ('-'-'-') 

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

这只是另一种写作方式

 #define TRUE 1 #define FALSE 0 

expression式'/'/'/'将会自行分割'/'/'/'的char值,结果为1。

expression式'-'-'-'将减去'-'的char值,从而得到0。

整个defineexpression式的括号都丢失了,这会导致代码中使用这些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式的值是01

为了历史的缘故,这些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式作为TRUEFALSE混淆macros也被Don Libes(1993)的“混淆的C和其他未解之谜”一书所涵盖。

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

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

这是一个讨厌的方式来陈述明显的。

编写TrueFalsemacros的方式很有趣。

由于许多解释已经提供/意味着一个1字节的数字(按照ASCII)分开时它给你1将被视为True ,同样-再次是一个字节数减去相同的价值,它给你0被解释为false

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

因此我们可以用任何我们喜欢的字符replace/或者-例如:

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

将保持原来的expression意义相同。