TRUE和FALSE宏的奇怪定义

Kes*_* GN 297 c c++ macros obfuscation boolean

我在编码书中看到了以下宏定义.

#define TRUE  '/'/'/'
#define FALSE '-'-'-'
Run Code Online (Sandbox Code Playgroud)

那里没有解释.

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

Jay*_*Jay 379

让我们看看:'/' / '/'意味着char文字/,除以char文字'/'本身.结果是一个,这听起来很合理TRUE.

并且'-' - '-'意味着char文字'-',从中减去.这是零(FALSE).

这有两个问题:首先,它不可读.使用10绝对更好.另外,正如TartanLlama和KerrekSB所指出的那样,如果您打算使用该定义,请在它们周围添加括号,这样您就不会有任何意外:

#include <stdio.h>

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

int main() {
        printf ("%d\n", 2 * FALSE);
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

这将打印char文字的值'-'(我系统上的45).

括号:

#define TRUE  ('/'/'/')
#define FALSE ('-'-'-')
Run Code Online (Sandbox Code Playgroud)

程序正确地打印为零,即使将真值乘以整数没有多大意义,但它只是一个例子,如果你没有用括号表示你的宏可能会咬你.

  • 实际上乘以真值是有意义的.对于检查缩进*should_indent将导致0或缩进,具体取决于should_indent是否没有分支.(我想这是一个不好的例子,当使用文本单分支无关紧要时,(我在着色器和XPATH中看到过这种技术(两者都太不同了,我不记得确切的形式)) (8认同)
  • 该死的我花了很多时间来理解它:甚至认为这是一个奇怪的事情,因为字形...不知道xD (6认同)
  • 很棒的解释.有金徽章! (4认同)
  • Alpedar - 但它没有*概念上*并且在matehmatically上做了感知 - 在这种情况下,使用`if`而不是将TRUE乘以整数将更清楚(并且在概念上有意义). (2认同)
  • 逻辑取反可以实现为`notx = TRUE- x;`,并且可以正常工作。除了TRUE-FALSE是-44(假设ASCII) (2认同)

Bla*_*arf 89

这只是另一种写作方式

#define TRUE 1
#define FALSE 0
Run Code Online (Sandbox Code Playgroud)

表达式'/'/'/'将自己划分char值,'/'结果为1.

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

但是整个define表达式周围的括号丢失了,这可能导致使用这些宏的代码出错.杰伊的回答很好地说明了这一点.

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

#include <iostream>

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

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

这是我们得到的:

True: 0
False: -44
Run Code Online (Sandbox Code Playgroud)

所以(bool) TRUE实际上会评估false,(bool) FALSE并将评估true.

  • 这个例子很好:) (4认同)

060*_*002 44

它相当于写作

#define TRUE 1
#define FALSE 0
Run Code Online (Sandbox Code Playgroud)

表达式'/'/'/'实际上做的是将字符/(无论其数值是什么)单独划分,因此它变为1.

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

写作会更好

#define TRUE ('/'/'/')
#define FALSE ('-'-'-')
Run Code Online (Sandbox Code Playgroud)

与其他更高优先级的运算符一起使用时,避免意外更改值.

  • 什么是"2*FALSE" - 两个错误是否正确? (35认同)
  • 大声笑!这就是为什么宏应该被正确括起来的原因. (5认同)

oua*_*uah 33

杰伊已经回答了为什么这些表达的价值是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);}
Run Code Online (Sandbox Code Playgroud)

(链接到这里的程序,有一个暗示这个程序在上面的IOCCC页面中做了什么.)

此外,如果我没记错这些表达式作为混淆宏,TRUE并且FALSE也被Don Libes(1993)的"混淆C和其他奥秘"一书中所述.


ana*_*and 7

True和写宏的热闹方式False.

已经提供/了许多解释意味着一个1字节的数字(按照ASCII),当它除以它时,它会给你1哪个将被视为True同样 -又是一个字节数,当减去它给你的相同值时0将被解释为false

#define TRUE  '/'/'/'
#define FALSE '-'-'-'
Run Code Online (Sandbox Code Playgroud)

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

#define TRUE  '!'/'!'
#define FALSE 'o'-'o'
Run Code Online (Sandbox Code Playgroud)

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


Fab*_*ien 6

让我们从真实开始吧.您可以将其读作'/' / '/',这意味着"字符'/'除以字符'/'".由于C中的每个字符都是一个数值(在一个字节上),因此可以将其读作"字符的ASCII值'/'除以相同字符的ASCII值",这意味着1(因为很明显, x/x是1).因此,TRUE是1.

因为FALSE,它的原因相同:'-'-'-'读取'-' - '-',即" - '的ASCII值减去' - ''的ASCII值,即为0.因此,FALSE为0.

这是一个令人讨厌的方式来说明显而易见的.

  • 这与ASCII无关. (7认同)
  • @Fabien:它不依赖于ASCII.`'/'/'/'`对于*any*有效字符集是1,无论是''/'== 47`(因为它是ASCII),或''/'== 97`(因为它在EBCDIC)或任何其他价值. (6认同)
  • @Pawel:符合C的实现不能将`'/''映射到'0`.该值保留给null字符. (4认同)
  • @ Matheus208如果帕维尔迂腐,那就是(' - ' - ' - '),因为他的观点基于一个未说明的条件; 将基思的言论描述为迂腐可能更多('/'/'/'),但我称之为"澄清"(并且添加的笑脸"迂腐"对我来说肯定是'/' - '/'.可能是(' - '/' - ')这些评论可以被称为迂腐,但是,1)在这个领域不是有点强制性的吗?2)他们让我思考; 3)我对某些事情比我更清楚.是的,我想我自己就是迂腐!(但我对"迂腐"的含义比我更清楚!;-) (3认同)
  • @Pawel:当然,我本来可以更明确的。但由于问题是关于 C(和 C++),这就是我所说的“任何 **valid** 字符集”的意思。 (2认同)
  • 你是迂腐的. (2认同)
  • @Matheus208:你说这是件坏事。 (2认同)