【问题标题】:-D name=definition and bitwise operator-D 名称=定义和位运算符
【发布时间】:2019-07-11 19:00:14
【问题描述】:

我试图了解下一个计算是如何执行的。

例如,如果这是我的终端命令

gcc ex2.c -D b+=2

为什么我会得到 5 个?

#include <stdio.h>

int main() 
{
#ifdef b
    printf("%d\n", 2 b | ~ 2 b);
#endif
    return 0;
}

2 b 表示 2*b ?

~ 2 b 表示 2*b 然后 ~ ?

【问题讨论】:

  • 这……很奇怪……不要学写和执行这样的代码。
  • 这是我做的一个测试中的一个问题
  • 根据this page -D b+=2 似乎不是一个有效的语法。
  • 我猜想测试的人都喜欢莎士比亚(“2 b | ~ 2 b”是“成为,或不是”的C)。有趣,但在学习环境中也有点烦人,这是非常人为的,在现实世界中,这样做的程序员很可能会在代码审查中得到……单词。

标签: c gcc bitwise-operators bitflags


【解决方案1】:

这很奇怪,它在解析命令行参数时有效,并且看起来像是来自 gccclang 的错误(或功能)。

看起来gcc 用空格替换了第一个= 登录宏声明。所以参数:

-D b+=2

等于

#define b+ 2

因为gcc有一个扩展来解释它,它等于

#define b + 2

预处理器输出:

printf("%d\n", 2 + 2 | ~ 2 + 2);

表达式2 + 2 | ~ 2 + 2 等于(2 + 2) | ((~ 2) + 2)(参见operator precedence),在twos complement 系统上等于4 | (-3 + 2) 等于4 | -1。在二进制补码上,-1 等于 0xff....ff,所以 4 | -1 等于 0xff...ff(因为它是二进制 OR),即 -1

【讨论】:

  • 所以对于 b+=3 我会得到 5 ?
  • 不知道,让我们看看:2 + 3 | ~ 2 + 3 = 5 | -3 + 3 = 5 | 0 = 5。是的,你会很幸运5
  • 这真的很难看。它也适用于更复杂的表达式,例如printf 'b\nb b\nb(3)' | gcc -E - -dD -D'b(=x)(x+x)'。我希望没有人将它用于实际编程,我什至没有看到 IOCCC 条目滥用它。
  • 我找到了the GCC code doing this, in cpp_define,这正是您的假设。不过,我没有找到这种行为的测试用例。
  • 还有the code for LLVM。也没有提到这个问题中滥用的功能。
【解决方案2】:

gcc ex2.c -D b+=2编译定义b+2所以源

#include <stdio.h>

int main() 
{
#ifdef b
    printf("%d\n", 2 b | ~ 2 b);
#endif
    return 0;
}

就像

#include <stdio.h>

int main()
{

    printf("%d\n", 2 + 2 | ~ 2 + 2);

    return 0;
}

对我来说打印-1


要查看预处理后的结果,请使用选项 -E :

/tmp % gcc ex2.c -E -D b+=2
<command-line>: warning: missing whitespace after the macro name
...
# 2 "ex2.c" 2

int main()
{

    printf("%d\n", 2 + 2 | ~ 2 + 2);

    return 0;
}

【讨论】:

  • 所以 ' ~ ' 运算符在 2 或 2+2 上?
  • @GiladRozmarin 由于运算符优先级,它位于 2 上,在这两种情况下结果都是 -1,因为将所有位都放在 1
  • 搞错了
  • @GiladRozmarin 不要忘记选项-E 了解附加的内容很有用,您可以在使用它之前添加一些#include 注释,以免产生很多行
猜你喜欢
  • 2018-12-17
  • 1970-01-01
  • 2019-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多