【问题标题】:Non-initialisation of proper array element causes undefined behavior [duplicate]未初始化正确的数组元素会导致未定义的行为[重复]
【发布时间】:2019-10-23 12:43:36
【问题描述】:

我在 VSC 中做了一些测试来检查数组的行为。我在一个测试的输出中遇到了这个问题,尽管数组元素被正确定义但没有初始化,但显然发生了未定义的行为(正确的意思是数组元素是用数组本身定义的,而不是额外的导致众所周知的未定义行为的数组边界)。

这是我的代码,下面是它的输出:

问题在于foo[4] 的输出是 8 而不是 0。

#include <stdio.h> 

int main()
{
    int foo[12];
    int i;

    foo[5] = 6; 
    foo[6] = 7;
    foo[7] = 8;
    foo[8] = 9;
    foo[9] = 10;
    foo[10] = 11;
    foo[11] = 12;

    for(i=0 ; i<=11 ; i++)
    {
        printf("foo[%d] = %d\n",i,foo[i]);
    }
}

输出:

foo[0] = 0
foo[1] = 0
foo[2] = 0
foo[3] = 0
foo[4] = 8
foo[5] = 6
foo[6] = 7
foo[7] = 8
foo[8] = 9
foo[9] = 10
foo[10] = 11
foo[11] = 12

此后我尝试了其他方法并想看看foo[5] 是否也会受到影响,如果我也没有对其进行初始化,但事实并非如此。 foo[4] 仍然有错误的值顺便说一句:

#include <stdio.h> 

int main()
{
    int foo[12];
    int i;

    // foo[5] = 6; 
    foo[6] = 7;
    foo[7] = 8;
    foo[8] = 9;
    foo[9] = 10;
    foo[10] = 11;
    foo[11] = 12;

    for(i=0 ; i<=11 ; i++)
    {
        printf("foo[%d] = %d\n",i,foo[i]);
    }
}

输出:

foo[0] = 0
foo[1] = 0
foo[2] = 0
foo[3] = 0
foo[4] = 8
foo[5] = 0
foo[6] = 7
foo[7] = 8
foo[8] = 9
foo[9] = 10
foo[10] = 11
foo[11] = 12

我的问题是:为什么在foo[4] 发生未定义的行为?该数组由 12 个元素正确定义。

【问题讨论】:

  • 你没有在任何代码 sn-p 中初始化foo[4]。因此,打印 foo[4] 是 UB,您不能保证任何特定的结果。
  • @Blaze 是的,我知道。但是为什么它也会导致未定义的行为呢?我已经正确定义了数组。
  • 除非您明确初始化局部变量(包括数组),否则它们的值和内容将是不确定的。在 C++ 中,即使读取不确定的值也是未定义的行为(不像 C,它只是可能,所以请选择你真正编程的语言)。
  • 是的,您已经定义了一个数组,但您从未定义它的值。这意味着它有一个未定义的值。
  • 是的,all 局部非静态变量也是如此。全局变量或局部静态变量将被初始化。

标签: c arrays undefined-behavior


【解决方案1】:

问题是关于foo[4] 的输出。

不仅如此。

问题在于数组的每个 未初始化 元素,您稍后会访问这些元素 - 这些元素具有 indeterminate(垃圾)值。

您无需初始化数组的前 5 个元素,而是在 for 循环中访问它们,该循环调用 Undefined Behavior (UB)。

您很幸运,您数组的前四个元素今天恰好在您的机器中,此时,已初始化为您希望它们成为的值。

这是我运行你的代码online得到的输出:

foo[0] = 0
foo[1] = 0
foo[2] = 4195741
foo[3] = 0
foo[4] = 0
foo[5] = 6
foo[6] = 7
foo[7] = 8
foo[8] = 9
foo[9] = 10
foo[10] = 11
foo[11] = 12

【讨论】:

  • 非常感谢您提供这些信息。我不知道这会导致未定义的行为。同样的事情是否适用于未初始化的(正常)变量?
  • 有一段时间我也不知道@RobertS,这就是为什么我赞成你的问题! :) 至于本地(如您所说的正常)变量,同样的理念也适用!检查此What happens to a declared, uninitialized variable in C? Does it have a value?。在那里,您也可以找到对标准的引用。希望有帮助!
  • 在 C89 中,不确定值被定义为未指定值或陷阱表示,并且调用 UB 访问不确定值的概念仅限于描述 general 的非规范性附件i> 可能调用 UB 的构造。在不知道int 是否具有陷阱表示的情况下,无法知道上述是否会定义行为。然而,在int 没有陷阱表示的平台上,上面会输出未指定的值。
【解决方案2】:

为什么在 foo[4] 处发生未定义的行为?数组是 用 12 个元素正确定义

一言难尽。

也就是说,当您如下定义本地数组时。

int foo[12];

foo 的每个元素在显式初始化之前都将具有不确定的值。

【讨论】:

  • 我不知道这个,非常感谢。您对此有任何文档参考吗?也许在标准中?当我不初始化它们时,同样的事情是否适用于普通变量?
猜你喜欢
  • 2013-08-12
  • 2020-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-16
相关资源
最近更新 更多