当前位置: 首页 > 知识库问答 >
问题:

为什么定义数组之外的第一个元素默认为零?

璩无尘
2023-03-14

我正在为C班的期末考试而学习。我们的教授给了我们这个练习题:

解释为什么代码会产生以下输出:120 200 16 0

using namespace std;
int main()
{
 int x[] = {120, 200, 16};
 for (int i = 0; i < 4; i++)
 cout << x[i] << " ";
}

该问题的示例答案是:

cout语句只是循环遍历数组元素,其下标由for循环的增量定义。数组初始化不定义元素大小。for循环定义了数组的大小,它碰巧超过了初始化元素的数量,因此最后一个元素默认为零。第一个for循环打印元素0(120),第二个打印元素1(200),第三个循环打印元素2(16),第四个循环打印默认数组值为零,因为元素3没有初始化。此时,i超过条件,for循环终止。

我有点困惑,为什么数组外的最后一个元素总是“默认”为零。为了进行实验,我将问题中的代码粘贴到IDE中,但将for循环更改为for(inti=0;I)


共有3个答案

颜举
2023-03-14

这会导致未定义的行为,这是唯一有效的答案。您的数组x在堆栈上仅为三个整数保留内存,读取第四个整数时在输出中看到的内容未知,在某些系统/处理器上,由于尝试读取不可寻址的内存(系统不知道如何访问此地址的物理内存),可能会导致硬件中断。得到0的事实实际上是偶然的。通过在clang(-fsanize=address选项)中使用地址消毒剂,您可以看到:

https://coliru.stacked-crooked.com/a/993d45532bdd4fc2

短输出为:

==9469==ERROR: AddressSanitizer: stack-buffer-overflow

您可以在编译器资源管理器上进一步研究它:

https://godbolt.org/z/P5f57Yfvs

您将看到gcc为您的阵列生成以下程序集:

    mov     DWORD PTR [rbp-16], 120
    mov     DWORD PTR [rbp-12], 200
    mov     DWORD PTR [rbp-8], 16
    mov     DWORD PTR [rbp-4], 0

事实上,第四个元素的值为0。但是,请参见本例的优化级别-its-g-so非优化。开始添加优化,比方说-O1,您将得到:

    mov     DWORD PTR [rsp+4], 120
    mov     DWORD PTR [rsp+8], 200
    mov     DWORD PTR [rsp+12], 16

更多的优化可能会完全优化您的阵列—将其放入寄存器中。

缑泓
2023-03-14

它不默认为零。示例答案是错误的。未定义的行为是未定义的;值可以是0,也可以是100。访问它可能会导致seg故障,或导致计算机格式化。

至于为什么它不是一个错误,这是因为不需要C来对数组进行边界检查。您可以使用向量并使用at函数,如果您超出边界,该函数会引发异常,但数组不会。

郗福
2023-03-14

我有点困惑,为什么数组外的最后一个元素总是“默认”为零。

在这份宣言中

int x[] = {120, 200, 16};

数组x正好有三个元素。因此,在数组边界之外访问内存会调用未定义的行为。

就是这个循环

 for (int i = 0; i < 4; i++)
 cout << x[i] << " ";

调用未定义的行为。数组最后一个元素之后的内存可以包含任何内容。

另一方面,如果数组被声明为

int x[4] = {120, 200, 16};

也就是说,对于四个元素,数组中没有显式初始值设定项的最后一个元素将被初始化为零。

 类似资料:
  • 输出8 好吧,我给出了 neg=-1,low=0、b=10、键盘=2、驱动器=3 的值,我的数组是 [3 1] [5 2 8] 我已经添加了键盘和驱动器值,将其存储在max数组中。当我将这些最大数组值与b if(max[i]进行比较时

  • 问题内容: 我很难理解算法中问题的根本原因。然后,通过逐步简化函数,我发现Python中对默认参数的求值行为不符合我的预期。 代码如下: 问题是,如果未显式给出属性,则Node类的每个实例都共享相同的属性,例如: 我不了解此设计决定的逻辑吗?为什么Python设计人员决定在定义时评估默认参数?这对我来说似乎很违反直觉。 问题答案: 另一种选择是重量级的-将“默认参数值”存储为函数对象的“ thun

  • 问题内容: 我有几个数组的形式: 然后我制作一个TreeSet像这样: 其中Patient是制造“ Patient”对象的不同类。然后,我遍历数组中的每个元素以创建多个患者,并将它们添加到我的体内,如下所示: 但是,当我去检查我的计算机时,它仅返回“ 1”-为什么会这样? 我知道我的对象运行良好,因为当我尝试执行相同的操作但使用相反的方法时,一切正常。所以我猜我在使用TreeSet错误。 如果有帮

  • 问题内容: 我正在使用“替换”功能删除div中的所有非数字值。 看来Jquery replace只影响第一个元素。 这是我的Jquery: HTML代码: 结果: 2011 c20ff113。c201gf76341。 我想要的结果是: 2011 20113 20176341 问题答案: 您有重复的ID,这是无效的,并且还有jQueryID选择器(或jQuery内部使用的任何其他ID选择器,例如do

  • 我必须编写一个名为productOfPrevious的方法,它接受一个整数数组,并返回一个与输入大小相同的整数数组。返回数组中的每个单元格都是该单元格与前面所有单元格的乘积。 这是我的密码。但我不知道为什么输出数组中的元素总是为零。 输入:{1,2,3,4,5} 我需要的输出:{1,2,6,24,120} 我获得的输出:{0,0,0,0,0} 我的代码有什么问题吗?

  • 我正在编写一个函数,该函数应该删除链表的最后一个元素 这是我对节点的定义 我有一个节点列表1,它为值1、2、3运行了3次insert函数 insert函数如下所示 现在我的delete_last_element函数如下所示 基本上,我的想法是,我会先看看第一个元素是否为空,如果是,我什么也不做,因为没有最后一个元素。然后我将curr设置为head->next以查看列表中的下一个元素,如果它为nul