双哈希使用情况

问题描述

在C99 6.10.3.3。(2)中(突出显示

如果在类似函数的宏的替换列表中,紧随其后的是参数 或后跟##预处理令牌,该参数将替换为相应的 参数的预处理令牌序列;但是,如果参数不包含 预处理令牌,将参数替换为地标预处理令牌

#include <stdio.h>
#define hash_hash(a,b) a ## b
#define mkstr(a) # a
#define in_between(a) mkstr(a)

void main(void)
{
    char p[] = in_between(a hash_hash(,) b);
    printf("%s",p);
}

输出

a  b

我用hash_hash(,)描述了突出显示的短语,结果作为标准的表示似乎是正确的。

但是我想知道是否像,那样省略了逗号hash_hash(),这是否不同于标准的解释(未定义的行为)? placemaker是否与空白相同?

解决方法

如果省略了逗号,,例如hash_hash(),那么这是否与标准的解释(未定义的行为)不同?占位符与空白相同吗?

是的,如果使用参数定义了宏,则参数必须用逗号定界符分隔。尝试定义多参数宏将违反标准规则,并且无法编译:

类似于函数的宏可以像真实函数一样接受参数。至 定义使用参数的宏,您可以在 宏定义中的一对括号使宏 功能类似。参数必须是有效的C标识符, ,以逗号分隔 和空白(可选)。

此外,

  • 因为此要求为well defined,所以它不是未定义行为的示例。
  • 在参考段落 (可选)空白中,表示空白可以是与定界符一起使用,但仅作为分隔符是不够的。
,

但是我想知道是否像,一样省略了逗号hash_hash(),这和标准的解释(未定义的行为)有区别吗?

在这种情况下,逗号是函数式宏调用语法的一部分。它在宏的参数列表中分隔参数。类似函数的宏的调用必须为该宏的每个命名参数提供一个值,而使用hash_hash()(不带逗号)则不会这样做。这将违反语言约束,因此,不仅行为不确定,而且符合C的实现必须在遇到这种违反时发出诊断信息。

placemaker是否与空白相同?

不。您可以将地标概念化为零长度的预处理标记。这样的事情不能在源代码中直接表示。它既不是空白也不是缺少预处理令牌。 “地标”可以很好地描述其性质和作用。

,

但是我想知道是否省略了逗号,例如hash_hash(),这是否不同于标准的解释(未定义的行为)?

我认为相关部分是C11 6.10.3 / 4重点:

约束

如果宏定义中的标识符列表不以省略号结尾,则在调用类似函数的宏时,参数的数量(包括不包含预处理令牌的那些参数)等于宏定义中的参数数量。

逗号将给出一个有效的标识符列表,没有预过程标记,但是如果没有标识符,标识符列表将与宏的参数数量不匹配。因此, hash_hash()是违反约束的,您应该得到诊断消息。