将数组指针增加到最后一项之外

Mar*_*ler 5 c arrays pointers

我在C编程和数组指针方面玩得很开心。

当我将数组指针超出数组大小时,有人可以解释发生了什么吗?

看起来我正在访问数组之后的存储单元,但我只是想确定一下。

  1. 这些数字有什么意思吗?
  2. 为什么最后一个数字为零?
  3. 程序应该能够访问尚未分配的内存吗?

这么多的问题!

int arr[] = { 1, 2, 3, 4, 5 };
int *xPtr = arr;

for(int i = 0; i < 10; i++) {
    printf("current pointer is %d\n", *xPtr++);
}
Run Code Online (Sandbox Code Playgroud)

结果是:

current pointer is 1
current pointer is 2
current pointer is 3
current pointer is 4
current pointer is 5
current pointer is 0
current pointer is 127926431
current pointer is -759946469
current pointer is -492049712
current pointer is 32766
Run Code Online (Sandbox Code Playgroud)

这是我发现正确遍历数组的唯一方法。它是否正确?

int arraySize = sizeof(arr) / sizeof(int);
for(int i = 0; i < arraySize; i++) {
    printf("current pointer is %d\n", *xPtr++);
}
Run Code Online (Sandbox Code Playgroud)

结果是:

current pointer is 1
current pointer is 2
current pointer is 3
current pointer is 4
current pointer is 5
Run Code Online (Sandbox Code Playgroud)

hyd*_*yde 6

您正在访问阵列外部的内存。数组只有5个元素,您可以增加指针,然后取消引用。实际上,这里有两种不良情况:您在数组外部取消引用,但同时也将指针增加了超出数组末尾的一步。都不允许。

这是不确定的行为,因此任何事情都可能发生。在这种情况下,您似乎只是在将数组后的内存内容解释为ints。在C程序的上下文中,它们只是垃圾值,因为一旦您在C中具有未定义的行为,所有的赌注都将关闭,程序可能崩溃甚至更糟。

如果要弄清楚具有UB的程序,则必须对其进行编译,然后查看该特定编译的汇编代码。请注意,下次编译时,结果可能会有所不同(编译器开关,编译器或库更新,不同的计算机...),并且新的汇编代码可能具有完全不同的行为(因为C代码具有UB)。通常,这是没有用的,UB是UB,尝试推理一下它的作用很少。


C没有数组边界检查,因此C编译器不执行任何检查。在具有内存保护功能的现代PC操作系统中,如果尝试访问未分配给它的内存但分辨率较粗的内存(例如4 KB页面),则操作系统将终止该程序,并且可能会有很多内存仍然属于您的程序,因此OS可能不会在阵列之后的兆字节中发现任何不良情况。


第二版看起来不错。只需记住,sizeof它仅对实际数组有效,而不对指针有效,对于函数的数组参数无效(因为尽管语法实际上是指针,而不是数组)。