奇怪的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。
整个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式的值是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和Falsemacros的方式很有趣。
由于许多解释已经提供/意味着一个1字节的数字(按照ASCII)分开时它给你1将被视为True ,同样-再次是一个字节数减去相同的价值,它给你0被解释为false
#define TRUE '/'/'/' #define FALSE '-'-'-'
因此我们可以用任何我们喜欢的字符replace/或者-例如:
#define TRUE '!'/'!' #define FALSE 'o'-'o'
将保持原来的expression意义相同。