C语言中能否用已有数组对象而非数组指针初始化二维数组
嘿,这个问题问到C数组的经典痛点上了!我完全懂你想做什么——你有三个现成的int[10]数组,想把它们作为数组对象直接塞进一个二维数组里,而不是用指向它们首元素的指针。那咱们直接说结论:标准C里确实没办法直接这么做,下面给你掰扯清楚原因和替代思路。
首先,你已经精准抓住了问题的核心:在C的表达式里,数组名会自动退化为指向首元素的指针。当你写int outer[][10] = { first, second, third };的时候,first、second、third这些数组名会立刻变成int*类型的指针,而outer作为二维数组,它的每个元素是int[10]类型的数组——指针和数组是完全不同的类型,编译器肯定会报错,因为类型不匹配。
为什么C不允许这么做呢?因为C里的数组是不可赋值的左值,你没法把一个数组对象直接“复制”或“绑定”到另一个数组的元素上。二维数组int outer[3][10]在内存里是一块连续的30个int的空间,每个outer[i]就是这块空间里的10个int;而你定义的first、second、third是完全独立的三块内存,C的初始化规则不允许把这些独立的内存块直接关联到二维数组的元素上——二维数组的元素必须由初始化器直接填充值,而不是引用外部的数组对象。
虽然没法直接用已有数组对象初始化,但有几个能达到类似效果的办法:
直接用值列表初始化二维数组
如果你的已有数组是有固定初始值的,直接把这些值写到二维数组的初始化列表里就行,这是最符合C初始化规则的方式:int outer[3][10] = { {0,0,0,0,0,0,0,0,0,0}, // 对应first的初始值 {0,0,0,0,0,0,0,0,0,0}, // 对应second {0,0,0,0,0,0,0,0,0,0} // 对应third };缺点是如果已有数组的内容很复杂,就得手动复制一遍值。
用指针数组模拟(但这不是真正的二维数组)
如果你只是想通过类似二维数组的语法访问已有数组,可以用指向数组的指针数组,但要注意这和真正的二维数组不一样——它的元素是指针,指向分散的内存块,而不是连续的内存:int first[10] = {0}; int second[10] = {0}; int third[10] = {0}; int (*outer[])[10] = {&first, &second, &third};这样你可以用
outer[i][j]来访问元素,但本质是指针间接访问,不是真正的二维数组。初始化后复制数组内容
先定义空的二维数组,再用memcpy把已有数组的内容复制进去,这是最接近你需求的“用已有数组填充二维数组”的方式:int first[10] = {1,2,3}; int second[10] = {4,5,6}; int third[10] = {7,8,9}; int outer[3][10]; memcpy(outer[0], first, sizeof(first)); memcpy(outer[1], second, sizeof(second)); memcpy(outer[2], third, sizeof(third));这样
outer是真正的二维数组,内存连续,内容和已有数组完全一致,但这是初始化后赋值,不是你想要的初始化时直接用数组对象。
再回到你的核心问题:能不能用已有数组对象而非指针初始化二维数组?答案是不行,C的语法和类型系统从根本上不允许这么做。数组名的退化特性和数组不可赋值的规则,导致你没法把已有数组对象直接作为二维数组的初始化器元素。
内容来源于stack exchange

