我被C(多维数组操作)中的输出卡住了

我被C(多维数组操作)中的输出卡住了,c,arrays,C,Arrays,我不明白这个程序是怎么运作的。我知道,当打印arr时,它返回的基址是8682,而arr[1]返回的下一个地址位置8686整数是4字节,但为什么arr[1][2]没有闪烁错误,因为arr[1][2]是越界的?在C中,越界数组访问不会抛出错误-事实上它甚至没有进行任何检查!取而代之的是,系统只会访问内存中发生的任何东西,这是C程序的主要危险之一 下面是对这里发生的事情的解释。在这里输入以下代码: 8682 8686 6 内部发生的情况实际上如下所示: arr[1][2] 二维数组在内部存储为一维

我不明白这个程序是怎么运作的。我知道,当打印arr时,它返回的基址是8682,而arr[1]返回的下一个地址位置8686整数是4字节,但为什么arr[1][2]没有闪烁错误,因为arr[1][2]是越界的?

在C中,越界数组访问不会抛出错误-事实上它甚至没有进行任何检查!取而代之的是,系统只会访问内存中发生的任何东西,这是C程序的主要危险之一

下面是对这里发生的事情的解释。在这里输入以下代码:

8682
8686
6
内部发生的情况实际上如下所示:

arr[1][2]
二维数组在内部存储为一维数组,每一行位于前一行之后:

*(arr + 1 * 2 + 2)  // the 2 comes from the second dimension size of the array

arr[1][2]的数学运算结果是访问arr[5],这就是为什么得到6作为值。

严格来说,这是未定义的行为。然而,如果你看看数组索引是如何处理的,你就会明白它为什么起作用

arr[3][2] = {2, 3, 4, 5, 6, 7};
// is the same as
arr[6] = {2, 3, 4, 5, 6, 7};
为什么arr[1][2]没有在arr[1][2]超出范围时闪烁错误


如果我的记忆正确,C不会抱怨数组越界错误。相反,它只允许您越界。

此程序的工作原理-它不允许,使用%d打印指针是未定义的行为。首先,在适当的时候将格式说明符更改为%p,并将指针强制转换为void*,然后我们可以再次发言。如果您需要边界检查,则语言为Turbo Pascal。C假设程序员知道他们在做什么。arr[1][2]与**a+1+2相同。等价性为:a[i][j]等价于**a+i+j。
arr[3][2] = {2, 3, 4, 5, 6, 7};
// is the same as
arr[6] = {2, 3, 4, 5, 6, 7};
arr
|
v
+-----+-----+-----+-----+-----+-----+
|  2  |  3  |  4  |  5  |  6  |  7  |
+-----+-----+-----+-----+-----+-----+

arr[0]
|
v
+-----+-----+-----+-----+-----+-----+
|  2  |  3  |  4  |  5  |  6  |  7  |
+-----+-----+-----+-----+-----+-----+

            arr[1]
            |
            v
+-----+-----+-----+-----+-----+-----+
|  2  |  3  |  4  |  5  |  6  |  7  |
+-----+-----+-----+-----+-----+-----+

               arr[1][0]
               |
               v
+-----+-----+-----+-----+-----+-----+
|  2  |  3  |  4  |  5  |  6  |  7  |
+-----+-----+-----+-----+-----+-----+

                           arr[1][2]
                           |
                           v
+-----+-----+-----+-----+-----+-----+
|  2  |  3  |  4  |  5  |  6  |  7  |
+-----+-----+-----+-----+-----+-----+