无法解释以下C++代码段的输出

Unable to explain the output for the following C++ snippet

本文关键字:输出 代码 C++ 无法解释      更新时间:2023-10-16
#include <bits/stdc++.h>
using namespace std;
int main() {
int dp[5][6];
memset(dp,0,sizeof(dp));
dp[1][0]=0;
for(int i=1;i<=9;i++){
dp[1][i]=1;
}
cout<<dp[2][0]<<endl;
cout<<dp[3][0]<<endl;
}

上面的代码片段会产生意外的输出:

1
0

但是,当我将 dp 数组大小更改为 dp[100][100] 时, 我得到的预期输出为:

0
0

我也尝试打印 2D 矩阵大小:

sizeof(dp)/sizeof(int)

我得到正确的值:dp[5][6] 为 30,dp[100][100] 为 10000。 我使用 linux 中的标准 g++ 编译器编译并执行了代码。 有人可以向我解释这种错误输出的原因吗?

数组的尺寸[5][6]。因此,当您尝试使用i19执行dp[1][i] = 1时,在某个迭代中,dp[1][6] = 1就完成了。由于"row"中的元素数量6,它正在做与dp[2][0] = 1相同的操作,因为该二维数组的所有元素都是按顺序存储的。

所以基本上当你尝试访问dp[1][i]时,就像startOffset + 1 * rowSize + i一样。i大于行大小。

作为旁注,使用memset对数组进行零初始化是C++的不良做法。最佳做法是使用聚合初始值设定项语法:

int dp[5][6] = {}; // Zero-initialize.

首先,这不是好的代码风格,但由于我不确定您要实现的目标,因此我不会建议如何改进它,而只是回答您的问题:解释输出。

在第一种情况下

int main() {
int dp[5][6];
memset(dp,0,sizeof(dp));
dp[1][0]=0;
for(int i=1;i<=9;i++){
dp[1][i]=1;
}
cout<<dp[2][0]<<endl;
cout<<dp[3][0]<<endl;
}

dp的第二个索引范围从05(因为您声明了int dp[5][6]并且C++数组都是从零开始的)。但是,然后从1循环第二个索引(ifor循环中)循环9。因此,索引6, 7, 8, 9超出范围,这通常会使您的程序崩溃。

它不会崩溃,因为您已经声明了一个 2d 数组,该数组在单个连续内存块中分配,因此dp[1][6]溢出到 2d 数组的下一部分。dp[1][6]相当于dp[2][0]

这就是为什么在第一种情况下,您会发现dp[2][0]等于1.

但是,当您将声明更改为dp[100][100]时,6, 7, ...是有效的第二个索引,因此它永远不会溢出,并且dp[2][0]保持其初始化值0

首先要提到的是 dp[5][6] 是一个 2D 数组,其中有 5 行,每行有 6 列。您可以将其可视化为网格。但现实是每一行都是按顺序排列的。第一行可以容纳 0 到 5。现在,当您在循环中分配 dp[1][6]=1 时,这意味着 dp[2][0] 被分配为 1,因为 dp[1][5] 是第一行的最后一个元素,第一行的第 6 个元素是第 2 行的第一个元素。你会得到相同的 dp[2][1]、dp[2][2] 和 dp[2][3]。但在 dp[2][4] 时会得到 0。

值得一提的是,在不同的体系结构中可能会有所不同。同样,不同的编译器可以以不同的方式工作。