在C中,二维数组的存储方式与线性数组一样,但它们使用双指针进行索引。也就是说,如果我们定义
int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}}.
a
首先指向类似
{p1 = 0x7fff5fbffb58 , p2 = 0x7fff5fbffb70, p3 = 0x7fff5fbffb88}
然后p1
指向1,p2
指向4,p3
指向7。
那么为什么编译器不允许从二维数组转换为双指针,这在理论上是可行的?尽管二维数组是逐个存储的,但索引信息总是可以传递给任意双指针。
答案 0 :(得分:9)
这在理论上是不可能的。不使用双指针索引2d数组 - 编译器将其转换为一个索引。例如,如果您有int a[3][5]
,并且访问a[i][j]
,则编译器会将其转换为((int[])a)[5*i+j]
。 (你的解释是完全错误的)
由于所有这些,如果要将int[][]
转换为int**
,则需要分配内存以保存所有子阵列的地址,并获取其地址。只有(int**)a
无效。
答案 1 :(得分:1)
您的示例说明了编译器无法执行此操作的原因:p1
,p2
和p3
的值计算,未存储。编译器知道p1
的地址,并在掌握数组大小知识的情况下计算其他两个地址。另一方面,对于双指针,所有三个指针都需要存储在顺序存储器位置,形成一个指针数组。
答案 2 :(得分:0)
将int[][]
转换为int**
需要引入充满数据的int
指针数组。我们喜欢c
因为没有明确要求而没有采取这种自由。
答案 3 :(得分:0)
因为C是这样说的。
(C99,6.3.2.1p3)“除非它是sizeof运算符或一元&的操作数。 运算符,或者是用于初始化数组的字符串文字,具有类型“数组类型”的表达式将转换为类型为“指向类型的指针”的表达式,该表达式指向数组对象的初始元素,而不是左值。“
此转换规则对于数组数组不是递归的。
转换后,int [N][M]
类型的对象的值为int (*)[M]
。
答案 4 :(得分:0)
因为是两件不同的事情。 int a [3] [3] ,在内存中是9个元素的数组。 int **你应该有一个包含3个元素的指针数组,每个元素都会指向另一个包含数据的数组。