c——int a[9]和a[3][3]之间的差值



之间有什么区别

#include <stdio.h>
int a[9]; 
int
main()
{
    printf("%dn", a[1]);
}

#include <stdio.h>
int a[3][3]; 
int
main()
{
  printf("%dn", a[1]);
}

我认为两者都导致在.bss部分放置相同的36字节内存缓冲区,有什么区别?还是a[3][3]的句法糖高于a[9] - a[3*3]

不,它们相同,它们代表不同的类型。参考您的代码,

  • 在第一种情况下,a是一维阵列。因此,a[1]属于int类型。

    §(要打印该值,%d即可。

  • 然而,在第二种情况下,a是二维阵列。因此,a[1]属于int [3]类型。

    §(作为函数参数传递时,它会衰减为指向第一个元素的指针,基本上是int *。您将需要%p来打印它(并根据%p格式说明符的要求将指针强制转换为void *(。

然而,如果你对这两个变量的内存布局感到困扰,你可以通过AnT或另一个详细说明多维数组内存布局的答案来检查另一个答案。

int a[3][3]int a[9]上的语义糖。原始内存布局相同(即,它是9个int的连续块(,但语言级别的访问语法不同。当访问a[3][3]作为a[i][j]时,编译器使用i * 3 + j公式将表观2D索引转换为1D索引。后一种索引转换方案很容易扩展到任何数量的维度。

有什么区别

int a1[9];

int a2[3][3];

(我已经更改了名称,这样我就可以更容易地谈论声明了。(

不同之处在于它们属于不同的类型。它们都有相同的底层存储器布局,每个都由一个连续的存储器区域组成,该区域的大小是int的9倍。但是a1是9个int对象的数组,而a2是3个对象的数组——每个对象是3个int对象的数组。它是一个多维数组,在C中,它恰好是数组的数组,没有更多,也没有更少。

区别不仅仅在于句法上的糖。对于某些操作,您可能会得到相同的生成代码,例如a1[1]a2[0][1]。但是,例如,a1[3]指的是数组a1的第4个元素,而a2[0][3],尽管您可能认为它指的是同一个元素,但实际上具有未定义的行为。(允许但不要求编译器执行运行时数组绑定检查,并允许假设数组引用没有超过索引数组对象的末尾。(

printf("%dn", a2[1]);

正如其他人所提到的,这具有未定义的行为。CCD_ 31是类型为CCD_。在大多数上下文中,数组类型的表达式被转换为指针类型的表达式,因此a2[1]的类型最终为int*,并产生指向a2第二行的初始元素的指针。要打印指针值,请使用%p——这需要类型为void*的参数,因此需要强制转换它:

printf("%pn", a2[1]);

推荐阅读:comp.lang.cFAQ第6节。

相关内容

  • 没有找到相关文章

最新更新