我想打印多维数组中包含的值。我知道,如果我们写类似arr[3][4]
的东西,那么arr[0]
就是指向多维数组中第一个元素的指针。我想问一下,为什么在程序打印多维数组中包含的数字后,这段代码会给我垃圾值?
这是代码:
#include <stdio.h>
#define ROW 3
#define COLL 4
int main(void) {
int arr[ROW][COLL]={{1,2,3,4},
{5,6,7,8},
{9,10,11,12}};
int *ptr;
for(ptr=arr[0];ptr<arr[ROW]+COLL;ptr++){
printf("%d ",*ptr);
}
printf("n");
return 0;
}
这是我编译上述代码时的结果:
1 2 3 4 5 6 7 8 9 10 11 12 -1079481492 134513936 0 -1079481352
但在将for循环更改为以下内容后:
for(ptr=arr[0];ptr<=arr[ROW-1]+COLL-1;ptr++)
代码工作并给出多维数组中包含的确切数字。
因为arr[ROW]
是越界访问。arr
中的最后一个有效位置是arr[ROW-1]
。因此,代码的第一个版本调用了未定义的行为。
指向最后一个元素的指针是
arr[ROW-1] + COLL - 1
所以你的循环应该是
for (ptr = arr; ptr < arr[ROW-1] + COLL; ptr++) {
数组的元素从0开始索引,因此矩阵中的最后一个元素是arr[ROW-1][COLL-1]
。
当指针到达arr[2] + COLL
时,并没有这样的元素,因为最后一行中最后一个元素的第二个坐标是[COLL-1]
。
数组的元素存储在1D中,因此arr[0] + 4
实际上是arr[1][0]
。当您递增ptr++
时,它会告诉编译器访问当前之后的下一个内存位置。因此,当ptr
指向a[0] + 4
时,它起作用,因为编译器访问a[0][0]
之后的第五个值,这实际上是下一行的第一个值arr[1][0]
,因为它们的内存位置彼此相邻。
当您的ptr
指向arr[4] + i, i = 0, 1, 2, 3
时,会得到错误的输出,因为这些元素不在您的数组中。
因为您的第一个元素1位于arr[0]+0
,
5处于arr[1]+0
,
9处于arr[2]+0
,
10处于arr[2]+1
,
11处于arr[2]+2
,
12,这是数组的最后一个元素,位于arr[2]+3
。
但是,即使在数组结束之后,for循环也会继续移动,也就是说,直到到达内存位置arr[3]+4为止。给你四个垃圾值,因为我们在arr[2]+3之后没有在内存中存储任何内容。
所以for循环应该是这样的:
for (ptr=arr; ptr <= arr[ROW-1]+COLL-1; ptr++);
相当于:
for (ptr=arr[0]; ptr <= arr[ROW-1]+COLL-1; ptr++);
因为arr[0]和arr指向存储器中的相同位置。注意-尝试阅读如何在多维数组中分配内存。