我在glibc中看到过调试printfs,如果定义了NDEBUG,内部定义为(void) 0.同样,Visual C++编译器的__noop也是如此.前者适用于GCC和VC++编译器,后者仅适用于VC++.现在我们都知道,上述两条语句都将被视为无操作,并且不会生成相应的代码;但我有个疑问.

对于__noop,MSDN说它是编译器提供的内部函数.到(void) 0~为什么编译器会把它解释为无操作?这是C语言的一种棘手用法,还是该标准明确说明了这一点?或者甚至这与编译器实现有关?

推荐答案

(void)0(+ ;)是一个有效的,但"什么也不做"的C++表达式,就是一切.它不会转换为目标体系结构的no-op指令,只要语言需要一个完整的语句(例如作为跳转标签的目标,或在if子句的主体中),它就只是一个空语句作为占位符.

EDIT:(根据Chris Lutz的评论更新)

应该注意的是,当用作宏时

#define noop ((void)0)

(void)可防止将其意外用作如下值

int x = noop;

对于上述表达式,编译器将正确地将其标记为无效操作.GCC吐error: void value not ignored as it ought to be,VC++吐'void' illegal with all types.

C++相关问答推荐

从带有句点的文件中读取数字(整数和小数)作为分隔符

如何判断作为参数传递的字符串是否是可修改的字符串

在链表中动态存储数据的问题

C 是否有 [[nodiscard]] 机制在忽略值时发出警告?

如果两个数字是相同的 0,则在 C++ 和 Root 中设置 0 条件

您可以使用 C 内联汇编来对齐指令吗? (没有编译器优化)

是否有更高性能的 powf(10,floorf(log10f(x))) 实现

在 C 中浮点到二进制

找到一种在 C 中调用具有不同参数的函数的方法

如何正确拦截 Linux 内核 5.* 中的系统调用?

OpenSSL 3 Diffie-Hellman 密钥交换 C++

OpenMP 线程 ID 如何与递归一起工作?

为什么这个 .c 文件 #include 本身?

如果缺少 const char* 数组初始化逗号,则生成编译器警告

我可以用 NULL 代替 0 的值吗?

对平方数字求和时是否需要明确处理负数或零?

为什么不自动假定#pragma 一次?

使用模数的 C 加法

为什么使用 abs() 或 fabs() 而不是条件否定?

uint16_t 的 += 运算符将分配的值提升为 int 并且不会编译