【问题标题】:C strange macro syntaxC奇怪的宏语法
【发布时间】:2016-08-26 15:57:19
【问题描述】:

我找到了这个 C 代码示例,我非常困惑:

#include <stdio.h>
#define M(a,b) a%:%:b

main()
{
  int a=1, b=2, ab[]={10,20}, c;
  printf( "%d", M(a,b)<:a:> );
  printf( "%d", M(a,b)<:a:>?a:b );
  printf( "%d", c=M(a,b)<:a:>?a:b );
}

有人能解释一下这应该做什么吗?它甚至不能在 Visual Studio 中编译,但我在线运行它(在 ideone.com 上)并打印了 2011,这也增加了混乱。

【问题讨论】:

  • 这是来自混淆 C 竞赛吗?
  • 无法解释,也没见过。它在 osx/darwin/unix 中编译。仅供参考,第一行评估并打印20,第二行1,第三行1
  • @GSerg:这些是 digraphs 而不是 trigraphs。尽管它们是相关的,但我认为这并不是一个真正的骗局。
  • @GSerg 将许多不同的混淆合并为一个 goo 的问题对于重复问题非常不利。而是将其作为副本关闭。

标签: c macros preprocessor-directive


【解决方案1】:

它使用了C digraphs,这是 1994 年对 C 标准的修订,因此是 C99 标准的一部分。用它们的实际字符交换有向图,你会得到:

#include <stdio.h>
#define M(a,b) a##b

main()
{
  int a=1, b=2, ab[]={10,20}, c;
  printf( "%d", M(a,b)[a] );
  printf( "%d", M(a,b)[a]?a:b );
  printf( "%d", c=M(a,b)[a]?a:b );
}

因此,请记住,a##b 会将输入合并为一个标识符。由于宏只是传递了ab,结果只是ab,所以你实际上有:

main()
{
  int a=1, b=2, ab[]={10,20}, c;
  printf( "%d", ab[a] );
  printf( "%d", ab[a]?a:b );
  printf( "%d", c=ab[a]?a:b );
}

c 的分配并不真正相关,所以我们可以摆脱它:

main()
{
  int a=1, b=2, ab[]={10,20};
  printf( "%d", ab[a] );
  printf( "%d", ab[a]?a:b );
  printf( "%d", ab[a]?a:b );
}

现在,让我们摆脱三元运算符(?:),因为我们可以静态地计算它(ab[a] 总是正确的,因为a 是 1 而ab[1] 是 20,即非零) :

main()
{
  int a=1, b=2, ab[]={10,20};
  printf( "%d", ab[a] );
  printf( "%d", a );
  printf( "%d", a );
}

现在,将变量替换为它们的实际值,即将ab[a] 替换为20,将a 替换为1

main()
{
  int a=1, b=2, ab[]={10,20};
  printf( "%d", 20 );
  printf( "%d", 1 );
  printf( "%d", 1 );
}

【讨论】:

  • 令人印象深刻的分析
  • 哇,这开启了一个充满可能性的全新世界。 :D 谢谢!
  • @Eutherpy:不。不,它没有。假装你从未见过。
  • @Eutherpy Digraphs 和 trigraphs 是一些非常糟糕的想法,它们被添加到标准中以支持世界各地的各种异国计算机键盘布局(而不是提出关键字标准)。它们已成为过去,如今它们被视为 100% 的不良做法。
  • 这些天他们应该添加对表情符号的类似支持?
猜你喜欢
  • 2010-11-24
  • 2011-03-23
  • 1970-01-01
  • 2017-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-14
  • 2012-12-17
相关资源
最近更新 更多