在不使用结果的情况下将结构指针转换为 void 的目的

Purpose of casting a struct pointer to void without using the result

我正在尝试理解以下 C 代码。

static unsigned
parent(const struct binheap *bh, unsigned u)
{
    (void)bh;
    return (u / 2);
}

(void)bh; 的目的是什么?它没有分配给任何东西,也不应该对输出产生影响。我能想到的唯一目的可能是作为一种针对空指针的断言。

对于上下文,该片段来自 the original implementation of a B-heap。该代码在其他地方也往往过于聪明,例如for (unsigned n = 2; n; n += n) { 在 n = 65536 处中断。

这通常是为了避免编译器警告。例如,如果在 gcc 中使用 -Wall -Wextra 进行编译,它会警告您没有使用 bh 如果您不进行强制转换为 void.

这只是为了避免编译器针对未使用的变量发出警告。如果没有强制转换,您的编译器将(尝试)警告您代码中有一个未使用的变量。

(void)bh; 在生成的代码 中没有效果。但是,对于许多编译器,它会阻止编译器发出有关参数 bh 未在函数中以其他方式使用的警告,这几乎可以肯定是程序员的意图。 bh 是一个结构指针是无关紧要的;如果此技术完全有效,则无论未使用参数的类型如何,它都会起作用。

C++ 有一种更优雅的方法来实现这一点,允许您省略不需要的任何参数的变量名 --

static unsigned
parent(const struct binheap *, unsigned u)
{
     return (u / 2);
}

-- 但是 C 不支持这个。一些编译器出于相同的目的进行了扩展,即使不是那么优雅,至少也更具自我描述性,例如海湾合作委员会

static unsigned
parent(const struct binheap *bh __attribute__((unused)), unsigned u)
{
     return (u / 2);
}

(void)bh; 技巧是唯一一种仅使用 ISO C 功能来抑制未使用参数警告的技术;另一方面,它不能保证工作,编译器发出的警告完全取决于该编译器,因此无论您做什么,您都已经处于实现定义的领域。

因为编译器警告

有些编译器会在函数中未使用变量时发出警告。见下文

#include <stdio.h>

void hello(int a, int b)
{
  int i = b + 1;
   printf("hello %d\n", i);
  return;
}

int main(void)
{
 hello(10, 20);
 return 0;
}

如下所示编译它以查看警告

$ gcc -Wunused-parameter a.c                                                                                                                                                                                                                            
a.c:3:16: warning: unused parameter 'a' [-Wunused-parameter]
void hello(int a, int b)
               ^
1 warning generated.