数组溢出c++ (at arr[0])

Array overflow c++ (at arr[0])?

本文关键字:arr at 溢出 c++ 数组      更新时间:2023-10-16

昨晚我教了我妹妹一些基本的代码如何读取输入,将其放入数组并打印到屏幕上。下面是代码:

int main() {
    int N;  // size of array
    cin >> N;
    int arr[N];
    for(int i = 1; i<= N; i++) {
        cin >> arr[i];
    }
    for(int i = 0; i<N; i++) {
        cout << arr[i] << endl;
    }
    return 0;
}

结果如下:

input :
4
2 3 4 1
output :
8
2
3
4

我没有任何线索为什么会发生这种情况,我试着检查代码,但它似乎很简单,对我来说已经正确了。

首先c++不支持变长数组,如果一个数组被声明为有N个元素,那么有效的索引范围是[0, N-1]

您可以自己动态分配所需大小的数组,也可以使用标准容器std::vector<int>

使用std::vector<int>,你可以写

#include <iostream>
#include <vector>
int main() 
{
    unsigned int n = 0;
    std::cout << "Enter number of elements: ";
    std::cin >> n;
    std::vector<int> v( n );
    std::cout << "Enter " << n << " elements: ";
    for ( int &x : v ) std::cin >> x;
    std::cout << "nThe array is ";
    for ( int x : v ) std::cout << x << ' ';
    std::cout << std::endl;
    return 0;
}

程序输出可能看起来像

Enter number of elements: 10
Enter 10 elements: 0 1 2 3 4 5 6 7 8 9
The array is 0 1 2 3 4 5 6 7 8 9 

您必须注意的第一件事是dasblinkenlight已经在他的回答中提到,可变长度数组是一种语言扩展。

那么你应该认为数组是基于零索引的。这是什么意思?让我们考虑一个大小为4的数组,表示为arr。然后它的元素可以作为arr[0], arr[1], arr[2]arr[3]访问。那么运行第一个循环时会发生什么呢?

for(int i = 1; i<= N; i++) {
    cin >> arr[i];
}

设置arr[1]arr[2]的a值为arr[N]。但是arr[N]指向内存中与数组无关的位置,因为数组的大小是N,并且所有数组都是从零开始的。数组的最后一个元素在这里arr[n-1]

不幸的是,在c++中没有任何对数组长度的检查,你可以这样做。例如,如果你在c#或Java中尝试过这个,那么你就会得到一个索引超出范围的异常。

如果您将代码更改为以下内容,那么您将得到预期的输出:

for(int i = 0; i<N; i++) {
    cin >> arr[i];
}
for(int i = 0; i<N; i++) {
    cout << arr[i] << endl;
}

你的代码在c++中是无效的,因为可变长度数组是一种语言扩展。

把这部分弄清楚后,考虑一下在第一个循环的最后一步中发生了什么:你访问了数组末尾以外的元素,这是未定义的行为。

你的第二个循环是正确的,所以你所需要做的就是纠正第一个循环的头,使其与第二个循环的头匹配。

N个元素的数组的索引从0到N-1(所以:N-1 - 0 + 1 = N个元素,一些数学)

for(int i = 1; i<= N; i++)修改为for(int i = 1; i< N; i++)