C中的括号运算符.以下代码中的效果如何

And*_*dre 4 c parentheses

当我在禁用宏时出现以下代码时,我正在使用宏来启用/禁用跟踪:

int main()
{

  ("Hello world");

}
Run Code Online (Sandbox Code Playgroud)

这段代码是有效的,我得到了预期的效果(当宏被禁用时没有任何反应),但我无法弄清楚到底发生了什么.编译器是否将括号视为"无名"方法声明?

为了使代码更清晰,代码是:

 #ifdef TRACE

    #define trace printf("%s %d -> ",__FILE__, __LINE__);printf
 else

    #define trace
 #endif

int main()
{

  trace("Hello world");

}
Run Code Online (Sandbox Code Playgroud)

提前致谢.

AnT*_*AnT 18

如果缺少函数名称(如第一个示例中所示),则它不是"括号运算符".它只是表达式的一个语法元素,它改变了运算符和操作数之间的关联.在这种情况下,它什么都不做.你拥有的只是一个表达

"Hello world";
Run Code Online (Sandbox Code Playgroud)

其值为value char *,并忽略该值.您可以将该表达式包含在冗余对中()

("Hello world");
Run Code Online (Sandbox Code Playgroud)

这不会改变任何事情.

你可以用同样的方式写

(5 + 3);
Run Code Online (Sandbox Code Playgroud)

在代码中间,获取一个计算结果为value的表达式,该表达式8立即被丢弃.

通常编译器不会为没有副作用的表达式语句生成代码.事实上,在C语言中,每个表达式语句的结果都被丢弃,因此唯一"有意义"的表达式语句是带有副作用的表达式语句.编译器通常非常擅长检测无效语句并丢弃它们(有时会发出警告).

警告可能很烦人,因此编写无效的表达式语句

"Hello world";
Run Code Online (Sandbox Code Playgroud)

可能不是一个好主意.通常,编译器将转换识别void为不生成此警告的请求

(void) "Hello world";
Run Code Online (Sandbox Code Playgroud)

因此,您可以考虑相应地重新定义宏.

当然,使用上述trace技术,你要记住,如果你把东西确实有宏的副作用作为参数

trace("%d\n", i++);
Run Code Online (Sandbox Code Playgroud)

然后以"禁用"形式,它将如下所示

("%d\n", i++);
Run Code Online (Sandbox Code Playgroud)

(两个子表达式,由逗号运算符链接到一个表达式中).i在这种情况下,增量的副作用仍然存在,它不会被禁用.整件事情相当于平淡无奇

i++;
Run Code Online (Sandbox Code Playgroud)

此外,如果您使用函数调用作为参数

trace(get_trace_name());
Run Code Online (Sandbox Code Playgroud)

"禁用"表格看起来像

(get_trace_name());
Run Code Online (Sandbox Code Playgroud)

并且编译器可能不够聪明,无法实现get_trace_name()应该丢弃调用.因此,使用宏时要小心.避免带副作用的参数,避免使用函数调用的参数,当然,除非您在禁用实际跟踪时保留副作用.