C奇怪的宏语法

时间:2016-05-01 23:15:49

标签: c macros preprocessor-directive

我找到了这个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,这也增加了混乱。

1 个答案:

答案 0 :(得分:38)

它利用了C digraphs,这是1994年对C标准的修订,因此也是C99标准的一部分。将digraphs与他们的实际角色交换出来,你得到:

#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和{ {1}}为20,即非零):

ab[1]

现在,将变量替换为实际值,例如main() { int a=1, b=2, ab[]={10,20}; printf( "%d", ab[a] ); printf( "%d", a ); printf( "%d", a ); } ab[a]20 a

1