C 奇怪的宏语法

C strange macro syntax

我找到了这个 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 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] 替换为 20a 替换为 1

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