用作自己的初始化程序的未初始化变量的行为是什么?

Hon*_*hen 15 c c++ initialization language-lawyer

我刚才下面的代码可以用铿锵/ GCC /铛++/G ++编译注意到,使用c99,c11,c++11标准.

int main(void) {
    int i = i;
}
Run Code Online (Sandbox Code Playgroud)

甚至-Wall -Wextra,没有一个编制者甚至报告警告.

通过修改代码int i = i + 1;和使用-Wall,他们可能会报告:

why.c:2:13: warning: variable 'i' is uninitialized when used within its own initialization [-Wuninitialized]
    int i = i + 1;
        ~   ^
1 warning generated.
Run Code Online (Sandbox Code Playgroud)

我的问题:

  • 为什么编译器甚至允许这样做?
  • C/C++标准对此有何看法?具体来说,这是什么行为?UB或实施依赖?

Jea*_*bre 11

这是一个警告,它与标准无关.

警告是启发式的"乐观"方法.仅当编译器确定它将成为问题时才会发出警告.在这种情况下,你有更好的运气clanggcc评论中所述的最新版本(参见我的另一个相关问题:为什么我在这个简单的例子中没有得到gcc的"未使用的未初始化"警告?).

无论如何,在第一种情况下:

int i = i;
Run Code Online (Sandbox Code Playgroud)

从来没有做过什么i==i.由于它没用,因此可能会完全优化分配.对于没有"看到"自我初始化作为问题的编译器,您可以在没有警告的情况下执行此操作:

int i = i;
printf("%d\n",i);
Run Code Online (Sandbox Code Playgroud)

虽然这会触发警告:

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

尽管如此,不要对此进行警告已经足够糟糕了,因为从现在开始i被视为初始化.

在第二种情况:

int i = i + 1;
Run Code Online (Sandbox Code Playgroud)

1必须执行未初始化值之间的计算.那里发生了未定义的行为.

  • `int i = i + 1` 的风险是 UB 是 UB,周期。此外,签名溢出。此外,当另一位编码员必须在稍后的某个时间理解该代码时,会很头疼。 (2认同)

dbu*_*ush 11

因为i在初始化自身时未初始化,因此当时它具有不确定的值.不确定的值可以是未指定的值陷阱表示.

如果您的实现支持整数类型的填充位,并且如果所讨论的不确定值恰好是陷阱表示,那么使用它会导致未定义的行为.

如果您实现不没有在整数填充,那么值就是不确定并没有任何不确定的行为.

编辑:

进一步详细说明,如果i从未在某个时刻采取过地址,那么行为仍然可以是未定义的.这在C11标准的6.3.2.1p2节中详细说明:

如果左值指定了一个自动存储持续时间的对象,该对象可以使用寄存器存储类声明(从未使用其地址),并且该对象未初始化(未使用初始化程序声明,并且在使用之前未对其进行任何赋值) ),行为未定义.

因此,如果您从未获取地址i,那么您有未定义的行为.否则,上述声明适用.


归档时间:

查看次数:

1315 次

最近记录:

6 年,7 月 前