一个区别是用括号将其包裹起来可以防止预处理器对函数式宏进行扩展。正如其他答案中提到的那样,这对于实际编译器并没有任何区别。
例如:
#define function(a, b) a + b
void function() {
}
void (function)() {
}
这在IT技术中非常有用,比如微软Visual Studio库背后的聪明头脑决定提供类似函数的宏,例如
min
和
max
。 (还有其他方法,如
#undef
可绕过此问题)。
请注意,对象宏(例如
#define function 3 + 4
)仍将被扩展。
预处理器只是一个愚钝的文本替换工具(相对于编译器而言,编译器是一个(聪明的)文本替换工具)。 它获取宏定义并在所有位置进行替换。 它不知道所替换内容的语义。
例如:
#define function 3 + 2
void function() {
}
预处理器看到单词function
,并在文本中将其替换为字符串3 + 2
。他不知道function
是函数声明和定义的id名称部分。预处理阶段后,实际编译阶段开始。因此,编译器实际上看到:
void 3 + 2() {
}
对他来说毫无意义且出现错误。
对于类似函数的宏定义
// somewhere buried deep in a header
预处理器也是做同样的事情,只不过它期望由逗号分隔的两个括号中的“标记”(即参数),并进行替换。 (再次不考虑语义):
int d = function(2, 3);
//will be replaced by the preprocessor to:
int d = 2 + 3; // passes compilation phase
void function();
// the preprocessor doesn’t find the arguments for function so it gives an error.
然而,如果遇到 (function)
,它不会尝试扩展它(忽略它)。这只是一个规则。
(5)
是合法的整数表达式?同样的问题也存在于(void function (void))
,你会问为什么不行呢?这是一个漫长而悲伤的故事,它起源于一个有趣但完全误导的概念:“声明语法遵循使用语法”,我们被困在其中。 - n. m.void function (void);
实际上是C
语法。 - Stefan Falk