如果缺少函数名称,如您的第一个示例所示,则它不是“括号运算符”。它只是改变运算符和操作数之间关联的表达式的句法元素。在这种情况下,它根本什么都不做。你所拥有的只是一种表达
"Hello world";
它评估为char *
类型的值,并且该值被忽略。您可以将该表达式包含在一对冗余的()
("Hello world");
这不会改变任何事情。
以完全相同的方式编写
(5 + 3);
在您的代码中间并获得一个计算结果为 value 的表达式,该表达式8
立即被丢弃。
通常编译器不会为没有副作用的表达式语句生成代码。事实上,在 C 语言中,每个表达式语句的结果都会被丢弃,因此唯一“有意义”的表达式语句是具有副作用的表达式语句。编译器通常非常擅长检测无效语句并丢弃它们(有时带有警告)。
警告可能很烦人,因此编写无效的表达式语句,例如
"Hello world";
可能不是一个好主意。通常,编译器将强制转换识别void
为不生成此警告的请求
(void) "Hello world";
所以你可能会考虑相应地重新定义你的宏。
当然,使用上述trace
技术,你必须记住,如果你把一些确实有副作用的东西作为你的宏的参数
trace("%d\n", i++);
然后在“禁用”形式下,它将如下所示
("%d\n", i++);
(两个子表达式,由逗号运算符链接成一个表达式)。在这种情况下,递增的副作用i
仍然存在,它不会被禁用。整个就相当于plain
i++;
此外,如果您使用函数调用作为参数
trace(get_trace_name());
“禁用”表格将如下所示
(get_trace_name());
并且编译器可能不够聪明,无法意识到get_trace_name()
应该丢弃对的调用。因此,在使用宏时要小心。避免带有副作用的参数,避免带有函数调用的参数,当然,除非您打算在禁用实际跟踪时保留副作用。