我在一本编码手册中看到了以下宏定义。
1 2
| #define TRUE '/'/'/'
#define FALSE '-'-'-' |
那里没有解释。
请向我解释这些将如何作为TRUE和FALSE工作。
- 我认为把真的定义为1,把假的定义为0是一种有趣的方式。
- 请注意,这是一个没有括号的糟糕想法。我的意思是对他们来说这是一个可怕的想法,但是如果没有你只是要求一个漫长的调试之夜。
- 我可以知道你所引用的编码书吗?
- 请注意,在C++中没有定义真和假的定义,因为已经有EDOCX1,0和1。当然,没有什么能阻止你将真定义为1,假定义为0,也许定义为2。
- 我希望这本书将其作为坏代码或故意模糊代码的一个例子。
- 我觉得这些可以用更具创造性的方式来写。埃多克斯1〔2〕怎么样
- @丹尼尔达拉纳斯在C中也没有定义它们的意义,只包括stdbool.h。
- 真是太糟糕了:(
- 为什么人们会这样?或者是因为一个模糊的C程序比赛?
- 除了括号,我觉得很有趣。IDK与Lundin的例子不同,这有什么不可读的。模糊的C程序竞赛条目包含许多"更糟糕"的技术。
- 好的,我现在就停下来。
- #define FALSE ("1"??(1??))
- @丹尼尔:难道不应该把"可能"定义为0.5吗?
- @Kaiserludi '/'/'/',但我假设只允许整数值。
- @丹尼尔:另一个想法是用rand()%2来定义maybe as rand()%2,所以有时候==true,有时候==false。
- 除了缺少括号外,这些宏非常聪明。注意,"非常聪明"是一种侮辱。
- @Lundin:如果你一直在使用不支持的pre-c99实现,你可以使用typedef enum { false, true } bool;。
- 非常有趣的宏。我们能知道这本书的名字吗?
- 显然,以这种方式编写1和0的人手头上有太多时间,没有考虑这些宏在表达式中的使用方式。
- 为什么true被专门定义为1,而不是更一般的!FALSE?
- 它不是一般的,只是长一些。
- 当键盘上的特定键被破坏时,这是定义布尔值的另一种方法。对于那些提到缺少括号的人来说,当他们不能键入"0"时,如何甚至键入')'?
- @panzercrisis:大概是因为!FALSE是(在ASCII系统上)-45,因为前面提到的缺少括号。也许作者尝试过你的想法,但没能弄明白为什么它行不通;-)
- 哪本书?好奇的人想知道。
- 是C代码书还是C++编码书?
- 在C中,是真的!0,不是1。所以这些定义都是错误的,也有一半是错误的。
- 你在哪本编码书中看到了这些宏定义?
- @泛文化:江户十一〔10〕并不比江户十一〔9〕更普遍。鉴于false是0,根据定义,!FALSE是1。
- @tmn:!0的值与1的值完全相同。(任何非零值在条件中使用时都被视为"真",但这不是!运算符的含义。)
- 这是我见过的最接近#define TRUE FALSE //Happy debugging suckers(stackoverflow.com/questions/184618/…)
- @布拉德利看到我发布的关于历史信息的答案
- 但是在哪里找不到文件呢?dailywtf.com/articles/what_is_Truth_x3f3;_
- 这只是一种失去所有朋友的礼貌方式。
- 烧掉那本书。不,真的。
让我们看看:'/' / '/'是指char字/除以char字'/'本身。结果是一个,这听起来对true是合理的。
而'-' - '-'是指char字的'-'从自身减去。这是零(false)。
这有两个问题:第一,它不可读。使用1和0绝对更好。此外,正如塔坦拉玛和克里克布所指出的,如果你要使用这个定义,请在它们周围加上括号,这样你就不会有任何意外:
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 ('-'-'-') |
程序正确地打印零,即使用一个整数乘以一个真值没有多大意义,但它只是一个意外错误的例子,如果你不用括号括起来,它可能会咬你。
- 该死的,我花了很多时间去理解它:S甚至认为它是一个奇怪的东西,如象形文字…不知道XD
- 事实上,用真值相乘是有意义的。例如,缩进*应缩进将根据是否应缩进而不进行分支而导致0或缩进。(我想这是个糟糕的例子,当处理文本时,单分支并不重要,(我在着色器和xpath中看到过这种技术(两者太不同,我不记得确切的形式))。
- alpedar——但它在概念上和实质上并没有使senso这样做——在这种情况下,使用if而不是将TRUE乘以整数会更清楚(并且在概念上是有意义的)。
- 很好的解释。有金徽章!
- 逻辑否定可以作为notx = TRUE- x;来实现,并且可以很好地工作。除了TRUE-FALSE是-44(假定为ASCII)
- 作为一个经常使用.net/web编码的人,这增强了我对c-guys作为pwfs的奇怪感觉——"没有朋友的人":d
- 很好的解释。我在一些编程比赛平台上看到过这样的定义,比如Topcoder,在比赛的某个时刻,你应该"黑客"别人的程序。这是迷惑人们的好方法。:)
这只是另一种写作方式
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;
} |
我们得到的是:
因此,(bool) TRUE将对false进行实际评估,(bool) FALSE将对true进行评估。
它相当于写作
1 2
| #define TRUE 1
#define FALSE 0 |
表达式'/'/'/'实际做的是将字符/(无论其数值是什么)本身除以它本身,因此它成为1。
同样,表达式'-'-'-'从自身减去字符-,并计算为0。
最好是写
1 2
| #define TRUE ('/'/'/')
#define FALSE ('-'-'-') |
以避免与其他更高优先级的运算符一起使用时意外更改值。
- 什么是2 * FALSE--两个错误是正确的吗?
- 大声笑!这就是为什么宏应该用括号括起来。
- 两个错误显然是连字符
- 在一个球体上的3个权利,你最终会在同一个地方
- @Kerreksb没有,但有三个左撇子。)
Jay已经回答了为什么这些表达式的值是0和1。
为了历史起见,这些表达"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页面中有这个程序所做的提示。)
另外,如果我能正确地记住,这些表达式是用于true和false的模糊宏,那么这些表达式也包含在don libes(1993)的《模糊C和其他奥秘》一书中。
为true和false编写宏的方式很滑稽。
正如所提供的许多解释一样,/表示一个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。
这是一种令人讨厌的表达显而易见的事情的方式。
- 这与ASCII无关。
- @Kerreksb,在实践中,是的,它是这样的,除非您碰巧开发了一个非常具体的体系结构,这可能与OP的问题无关。
- @法比安:它不依赖于ASCII码。对于任何有效字符集,'/'/'/'都是1,无论是'/' == 47(ASCII格式),还是'/' == 97(EBCDIC格式)或任何其他值。
- @基思汤普森好吧,不是任何字符集-只是那些不映射'/' == 0的有限子集,而ASCII(或EBCDIC)就是很好的例子…
- @pawel:一致的C实现不能将'/'映射到0。该值是为空字符保留的。
- @keitthththompson:)如果我们说的是iso c,那么是真的-它将空字符定义为零字节,但是-您认为任何字符集都不会停止任意字符集,将空字符指定为可视glyph '/'。
- @帕维尔:当然,我本可以说得更清楚的。但是问题是关于C(和C++)的,这就是我所说的"任何有效的字符集"。
- 你太学究了。
- @Matheus208如果Pawell是个书呆子,那就是("-"—"—"),因为他的观点是基于一个未声明的条件;把Keith的评论描述为书呆子可能更多("/"/"/"),但我会称之为"澄清"(加上微笑的"书呆子"对我来说显然是"/-"/)。可能是(‘-’/’-’)把这些评论放在一起可以称为学究式的,但是,1)在这个领域,这不是强制性的吗?2)他们让我思考;3)我在某些事情上比以前更清楚了。是的,我想我自己也是个学究!(但我比以前更清楚"学究式"是什么意思!;-)
- @马修:你这么说好像是件坏事。
- 真的。这太棒了。@乔拉,讨论"学究式"定义的荣誉。我向你们所有人表示最深切的祝贺,感谢你们为提高互联网的准确性所做的不懈努力。