具有参数的宏与具有相同名称的变量的宏扩展

时间:2012-06-11 16:46:37

标签: c gcc macros c-preprocessor

考虑以下 C 计划(忽略双重副作用问题):

#define max(a, b) (a>b?a:b)

int main(void){
    int max = max(5,6);
    return max;
}

GCC预处理器将其转换为:

int main(void){
    int max = (5>6?5:6);
    return max;
}

这非常好,因为您不必担心maxmax()之间的无意碰撞。 GCC manual说:

  

类似函数的宏只有在其名称后面带有一对括号后才会展开。如果你只写下这个名字,那就不用了

这是标准化的还是按惯例完成的事情?

1 个答案:

答案 0 :(得分:5)

是的,这里的行为定义明确。

您的宏max是一个类似于函数的宏(即,当您定义它时,其名称后面紧跟左括号并且它接受参数)。

如果使用max后跟左括号,则稍后在代码中使用max只是对该宏的调用。因此,这些不会调用max宏:

int max;
max = 42;

但是这些都会调用max macro:

max(1, 2)
max (1, 2)
max
(
    1, 2
)
max()

(注意,最后一行是格式错误的,因为参数的数量与参数的数量不匹配。但这仍然是一个宏调用,并且会导致编译错误。)

此行为是由C语言标准强制执行的。 C99§6.10.3/ 10指出在定义了类似函数的宏之后,

  

类函数宏名称后跟(作为下一个预处理标记的每个后续实例引入了预处理标记序列,该标记由定义中的替换列表(宏的调用)替换。