无法理解在C中访问二维数组的这种方式

无法理解在C中访问二维数组的这种方式,c,arrays,pointers,multidimensional-array,casting,C,Arrays,Pointers,Multidimensional Array,Casting,我无意中看到了这段代码,发现很奇怪它居然能打印出5。我不明白为什么对int*的转换使得它基本上是一个一维数组。有人能解释一下吗 int main() { int v[2][3] = {{1,2,3},{4,5,6}}; int* c = (int*)v; printf("%d\n", c[4]); } 让我们谈谈数组订阅是如何工作的 首先,请记住数组下标操作a[i]被定义为*a+i-也就是说,给定地址a,偏移量i元素不是字节!从该地址,取消引用结果: +---+

我无意中看到了这段代码,发现很奇怪它居然能打印出5。我不明白为什么对int*的转换使得它基本上是一个一维数组。有人能解释一下吗

int main()
{
    int v[2][3] = {{1,2,3},{4,5,6}};
    int* c = (int*)v;
    printf("%d\n", c[4]);
}

让我们谈谈数组订阅是如何工作的

首先,请记住数组下标操作a[i]被定义为*a+i-也就是说,给定地址a,偏移量i元素不是字节!从该地址,取消引用结果:

   +---+
a: |   |
   +---+
   |   |
   +---+
    ...
   +---+
   |   | <--- a + i
   +---+
左边的图片是带有int*指针的int对象序列,右边的图片是带有int*[3]指针的int[3]对象序列

现在发生的是,你得到了v的第一个元素的地址,但是你把它当作int*,而不是int*[3]:

你基本上是在拍右边的照片,然后假装它是左边的照片。因此c[4]对应于序列中的第5个元素,在本例中为5

现在,这个行为是未定义的-int*[3]和int*是不兼容的类型,并且尝试以这种方式访问v的元素不能保证有效。更安全的方法是使用

int *c = &v[0][0]; // int * = int *

不兼容的类型不需要强制转换,您可以获得完全相同的效果。

让我们来谈谈数组订阅是如何工作的

首先,请记住数组下标操作a[i]被定义为*a+i-也就是说,给定地址a,偏移量i元素不是字节!从该地址,取消引用结果:

   +---+
a: |   |
   +---+
   |   |
   +---+
    ...
   +---+
   |   | <--- a + i
   +---+
左边的图片是带有int*指针的int对象序列,右边的图片是带有int*[3]指针的int[3]对象序列

现在发生的是,你得到了v的第一个元素的地址,但是你把它当作int*,而不是int*[3]:

你基本上是在拍右边的照片,然后假装它是左边的照片。因此c[4]对应于序列中的第5个元素,在本例中为5

现在,这个行为是未定义的-int*[3]和int*是不兼容的类型,并且尝试以这种方式访问v的元素不能保证有效。更安全的方法是使用

int *c = &v[0][0]; // int * = int *

没有强制转换来绕过不兼容的类型,您可以获得完全相同的效果。

此程序具有未定义的行为。v不是指向int的指针,并且与int不兼容。该程序似乎可以执行任何操作。这有帮助吗@n、 代词是m。具有不兼容的类型并不排除强制转换valid@M.M强制转换本身有效,随后的取消引用无效。@n.“代词m。我同意访问前3个元素之外的元素会有问题,但我认为访问第一行是定义良好的。我们可以从强制转换规则推断,强制转换的结果指向第一个int的同一内存位置,并且取消引用指向int的int*定义良好。该程序具有未定义的行为。v不是指向int的指针,并且与int不兼容。该程序似乎可以执行任何操作。这有帮助吗@n、 代词是m。具有不兼容的类型并不排除强制转换valid@M.M强制转换本身有效,随后的取消引用无效。@n.“代词m。我同意访问前3个元素之外的元素会有问题,但我认为访问第一行是定义良好的。我们可以从强制转换规则推断,强制转换的结果指向第一个int的同一内存位置,并且取消引用指向int的int*定义良好。类型兼容性与此无关类型兼容性与此无关