C语言中未知大小数组(incomplete type)的相关疑问
嘿,这个问题问得特别到位,刚好触及C语言数组类型规则里容易混淆的点,咱们一点点理清楚:
先看你碰到的两种数组定义情况:
当你写:
int n[];编译器会直接抛出错误:
incomplete type "int []" is not allowed
这是因为这种写法完全没指定数组的大小,编译器根本不知道要给它分配多少内存,也没法处理任何需要依赖数组长度的操作——这种类型就是C语言里说的「不完整类型(incomplete type)」,直接使用这种类型的变量是被禁止的,毕竟编译器连它的基本信息都摸不清。但换成下面这种初始化的写法:
int n[] = {1,2,3};情况就完全不同了!编译器会自动扫描初始化列表里的元素数量,这里有3个int元素,它就会隐式地把数组大小确定为3,相当于你直接写了
int n[3] = {1,2,3};。这时候数组的类型就从「不完整」变成了「完整类型」,编译器对它的大小、内存布局都门儿清,自然不会报错。
接下来逐个解答你的疑问:
没错!第二个例子里的数组确实不再是不完整类型了。初始化列表就像给编译器递了个小纸条,告诉它数组的具体长度,直接把不完整的类型给补全了。
至于为什么不能使用不完整类型的数组,核心原因就是编译器必须明确知道类型的大小,才能正确分配内存、执行各种类型相关的操作。比如你提到的
int n[][] = {{1,2},{3,4}};,C语言里的二维数组本质是「数组的数组」,这种写法里第一维的大小或许还能通过子数组的数量推断,但第二维的大小完全没指定——编译器没法确定每个子数组该占多大空间,哪怕你初始化里的子数组长度看起来一样,C语言的规则也不允许这种模糊的定义。
要是想让这个二维数组合法,你得指定除了第一维之外的所有维度的大小,比如改成这样:
int n[][2] = {{1,2},{3,4}};
这时候编译器知道每个子数组是2个int,再结合初始化列表里的2个子数组,就能推断出第一维的大小是2,类型也就完整了,这样写就完全没问题。
内容来源于stack exchange

