我知道gcc中有一个未初始化的警告可以告诉你变量是否未初始化。这对我来说很清楚。但我想知道什么是“可能已初始化”警告?
GCC是否不确定是否已初始化。或者考虑一下,代码初始化正确,GCC认为“可能”它没有初始化。如果编译器不确定为什么我应该发出这个警告呢?
现在我可以使用-Wno-maybe -ininitialized禁用警告或在代码中修复。
但我的问题是这意味着什么?为什么gcc认为它可能没有初始化。 GCC确定变量已初始化,因为我没有得到-Wuninitialized。
我正在使用GCC 4.8 Fedora 21 x86_64
如果有人能够证明这个警告是如何触发的,我也很感激。
答案 0 :(得分:3)
在提出这些问题之前,你应该仔细查看GCC手册。
对于自动变量,如果存在来自该函数的路径 进入使用初始化的变量,但存在 该变量未初始化的其他一些路径, 如果编译器无法证明未初始化的路径,则会发出警告 不会在运行时执行。这些警告是可选的,因为 GCC不够聪明,无法查看代码可能出现的所有原因 尽管看起来有错误但也是正确的。
当GCC不确定变量是否已初始化时,不会生成此警告。在变量未始终初始化时发出。
以下是手册中略有修改的示例:
void foo(int y)
{
int x;
switch (y)
{
case 1: x = 1;
break;
case 2: x = 4;
break;
case 3: x = 5;
}
bar(x);
}
答案 1 :(得分:2)
有些情况下编译器可以清楚地检测到某些内容尚未初始化:
void func1(int x);
void func()
{
int x;
func1(x); // x is definitely not initialized when calling func1;
}
但在某些情况下,变量CAN已经初始化:
void func(int y)
{
int x;
if (y == 1)
x = 7;
else if (y == 2)
x = 14;
// If we get here, is x initialized or not?
func1(x);
}
现在,如果您和我确定y
总是 onw或2,那么上面的代码没有问题。但是,如果我们将y
称为三,x
尚未初始化,func1
将对未指定的值进行操作。如果启用-Wmaybe-uninitialized
,编译器将对此情况发出警告。
解决方法是告诉编译器不要期望任何其他值,例如使用assert
:
void func(int y)
{
int x;
assert( y == 1 || y == 2 && "Can't deal with y not in { 1, 2 } ");
if (y == 1)
x = 7;
else if (y == 2)
x = 14;
// If we get here, is x initialized or not?
func1(x);
}
现在,编译器将知道assert
的结果不允许y
为1或2以外的任何值,因此涵盖了所有有效值。 <{1}}无法返回无效值。
[当然,标准并未声明assert
具有此效果。这是呼叫流分析结合数据流分析和理解assert
的作用 - 我知道gcc和clang都理解这种结构,并且很乐意在没有警告的情况下保留上述代码]