有一个关于以下代码的指针我无法弄清楚:函数set_array([][9])
中的部分,编译器给出的部分允许这个而不是正常的完整表达式set_array([4][9])
。但是在{{ 1}}部分main
,int array1[4][9]
不允许。
array1[][9]
对此有何解释?
答案 0 :(得分:2)
在函数调用数组中实际上被视为指针,因此在函数定义中
t_array[][9]
实际上是(*t_array)[9] //pointer to array
但是在数组的声明中,如果声明静态数组,则必须明确地给出大小
这样编译器就会为数组分配那么多内存。因此,array1[4][9]
是正确的,而array1[][9]
是错误的。
但是如果你正在做array1[][9]
,那么你必须提供初始化列表。
答案 1 :(得分:2)
作为比较(C89):
当你写
int a[]
compilre不知道需要为'a'分配多少内存,在这种情况下编译器需要使用初始化来确定数组的大小:
int a[] = {1,2,3}; // sizeof(a)==sizeof(int)*3
当你只写
int a[][9];
编译器不知道'a'有多大,因此无法分配足够的内存
如果您将数组作为参数
void foo(int a[][9])
该函数不需要知道两个维度有多大,因为它没有分配任何东西,它只是引用'a'。从参数中,函数知道它应该在解除引用时将'a'视为多维数组(其中第一个维是任意数)。
答案 2 :(得分:1)
在C中,你必须在静态声明数组时为数组大小赋值,否则编译器不会知道要为该变量分配多少内存。
当你将数组作为array [] [9]传递时,它的工作原理是因为编译器只需知道数组中元素的大小,而不知道它包含多少元素。因此,将array [] []作为参数传递将不起作用,因为编译器不知道存储的元素的大小。
答案 3 :(得分:1)
您可以使用初始化列表声明和初始化而不指定第一个维度:
int array1[][9] = {
{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9},
};
在C中,如果您内联初始化数组,则只需要从第二个开始指定维数大小。它们是编译器生成索引的代码所必需的,请记住多维数组(在C中)是一个连续缓冲区。
答案 4 :(得分:1)
这是因为当你做两件事时:
首先,您要声明一个名为array1
的变量。在C中,编译器需要知道您声明为您保留该内存量的空间量。所以你必须指定数组的完整大小:
int array1[4][9];
这样您的编译器就知道您需要分配4 * 9
个整数。
现在,在您的函数中,编译器不需要知道数组的大小(在数组转换为函数调用的指针的场景后面),它只需知道其元素的大小。因此t_array
是指向大小为9 * sizeof(int)
的元素的指针。正因为如此,您可以按照您声明的方式声明您的功能:
void set_array(int t_array[][9])
但也可以声明所有尺寸尺寸:
void set_array(int t_array[4][9])
但它对编译器无关紧要。
答案 5 :(得分:0)
你不能分配给数组,你只能初始化它们,所以你必须一次完成所有这些:
int array1[4][9] = {
{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9},
};