在 C 中抑制“未初始化的变量警告”的不同方法

red*_*0ct 8 c gcc initialization clang linux-kernel

我遇到过多次使用uninitialized_var()旨在消除警告的宏,例如:

warning: ‘ptr’ is used uninitialized in this function [-Wuninitialized]
Run Code Online (Sandbox Code Playgroud)

对于 GCC ( <linux/compiler-gcc.h>) 它是这样定义的:

/*
 * A trick to suppress uninitialized variable warning without generating any
 * code
 */
#define uninitialized_var(x) x = x
Run Code Online (Sandbox Code Playgroud)

但我也发现它<linux/compiler-clang.h>以不同的方式定义了相同的宏:

#define uninitialized_var(x) x = *(&(x))
Run Code Online (Sandbox Code Playgroud)

为什么我们有两种不同的定义?出于什么原因,第一种方式可能不够?第一种方式是否仅适用于 Clang 或在其他一些情况下也不够?


示例:

#define uninitialized_var(x) x = x

struct some {
     int a;
     char b;
};

int main(void) {
     struct some *ptr;
     struct some *uninitialized_var(ptr2);

     if (1)
         printf("%d %d\n", ptr->a, ptr2->a); // warning about ptr, not ptr2
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*hil 5

编译器必须将某些结构识别为作者有意为之,否则编译器会对此发出警告。例如, given if (b = a),GCC 和 Clang 都警告将赋值用作条件,但if ((b = a))即使它在 C 标准方面是等效的,它们也不会警告。这个带有额外括号的特殊结构只是被设置为一种告诉编译器作者真正想要这段代码的方式。

同样,x = x已设置为告诉 GCC 不要警告x未初始化的一种方式。有时一个函数可能看起来有一个代码路径,在该路径中使用一个对象而没有被初始化,但作者知道该函数不打算与会导致执行该特定代码路径的参数一起使用,并且,出于效率的原因,他们希望使编译器警告静音,而不是添加对程序正确性实际上不必要的初始化。

Clang 可能被设计为不识别 GCC 的习惯用法,因此需要一种不同的方法。