Activity solution[a][b];
...
Activity **mother = solution;
我想将一个二维对象数组转换为指向指针的指针。我该如何做到这一点?
我在谷歌上搜索了一下,但只找到了一维数组的例子。
Activity solution[a][b];
...
Activity **mother = solution;
我想将一个二维对象数组转换为指向指针的指针。我该如何做到这一点?
我在谷歌上搜索了一下,但只找到了一维数组的例子。
仅仅进行转换是没有用的。二维数组类型和指向指针的类型之间没有任何兼容性。这样的转换没有意义。
如果你确实需要这么做,你必须引入一个额外的中间"行索引"数组,它将连接二维数组语义和指向指针语义之间的差距。
Activity solution[a][b];
Activity *solution_rows[a] = { solution[0], solution[1] /* and so on */ };
Activity **mother = solution_rows;
现在访问mother[i][j]
将使您能够访问solution[i][j]
。
array[i]
”等同于表达式“*(array + i)
”。可以看到,执行数组索引操作不需要知道数组大小。但是,对于二维数组,元素按“行优先”顺序存储,这意味着零行中的所有元素首先存储,其次是第一行中的元素,其次是第二行中的元素,依此类推。因此,表达式“array[i][j]
”等同于表达式“*(array + (i * ROW_SIZE) + j)
”,其中“ROW_SIZE
”是每行中元素的数量。因此,执行数组索引操作需要知道数组的行大小,将数组变量转换为指针会丢失该信息。char firstName[4] = { 'J', 'o', 'n', '\0' }
和 char lastName[4] = { 'M', 'e', 'e', '\0' }
。让我们看一下可能的内存布局:+------------+-------+
| Address | Value |
+------------+-------+
| 0x76543210 | 0x4A | <- firstName[0] - 'J'
| 0x76543211 | 0x6F | <- firstName[1] - 'o'
| 0x76543212 | 0x6E | <- firstName[2] - 'n'
| 0x76543213 | 0x00 | <- firstName[3] - '\0'
+------------+-------+
| 0x76543214 | 0x4D | <- lastName[0] - 'M'
| 0x76543215 | 0x65 | <- lastName[1] - 'e'
| 0x76543216 | 0x65 | <- lastName[2] - 'e'
| 0x76543217 | 0x00 | <- lastName[3] - '\0'
+------------+-------+
cout << firstName << ' ' << lastName
,您将得到:
0x76543210 0x76543214
这些数组实际上只是指向它们的第一个元素的指针!这说明了数组指针衰减,您可以在此处阅读更多信息:http://en.cppreference.com/w/cpp/language/array#Array-to-pointer_decay
在我们继续之前,有一些重要的事情需要注意,char
正好占用1个字节,因此数组中每个后续char
的地址将简单地是下一个地址。这被下标运算符利用,例如: firstName[1]
等同于*(firstName + 1)
。对于占用超过1个字节的任何其他类型,这也是正确的。例如: short siArray = { 1, 2, 3, 4 }
,siArray
的可能内存布局如下:+------------+--------+
| Address | Value |
+------------+--------+
| 0x76543218 | 0x0001 | <- siArray[0] - 1
| 0x7654321A | 0x0002 | <- siArray[1] - 2
| 0x7654321C | 0x0003 | <- siArray[2] - 3
| 0x7654321E | 0x0004 | <- siArray[3] - 4
+------------+--------+
< p >即使< code>cout << siArray << ' ' << &(siArray [1])将输出:
< blockquote>
< p>0x76543218 0x7654321A
< p>< code>*(siArray + 1)仍将索引< code>siArray的相同元素,如< code>siArray [1]。这是因为在执行指针算术c++时,会考虑所操作地址的类型,因此增加< code>short *实际上会将地址增加< code>sizeof(short)。您可以在此处阅读有关指针算术的更多信息:http://en.cppreference.com/w/cpp/language/operator_arithmetic
最后让我们看一下c ++如何存储二维数组。假设:char name[2][4] = { { 'J','o','n','\0' },{ 'M','e','e','\0' } }
,可能的内存布局如下:+------------+-------+
| Address | Value |
+------------+-------+
| 0x76543220 | 0x4A | <- name[0][0] - 'J'
| 0x76543221 | 0x6F | <- name[0][1] - 'o'
| 0x76543222 | 0x6E | <- name[0][2] - 'n'
| 0x76543223 | 0x00 | <- name[0][3] - '\0'
| 0x76543224 | 0x4D | <- name[1][0] - 'M'
| 0x76543225 | 0x65 | <- name[1][1] - 'e'
| 0x76543226 | 0x65 | <- name[1][2] - 'e'
| 0x76543227 | 0x00 | <- name[1][3] - '\0'
+------------+-------+
由于我们知道一个一维数组的值实际上只是一个指针,从这个内存布局中可以看出,name [0]
不是 指针,它只是第一个数组的第一个字符。因此,name
不包含 2个一维数组指针,而是包含了这两个数组的内容。(顺便说一下,在32位机器上不存储指针可以节省8个字节的内存,这对于一个8字节的二维数组来说相当可观。) 因此,试图将 name
视为 char**
将会尝试使用字符作为指针。
char*
来使添加1只是简单的加1。例如:const short si2DArray[2][3] = { { 11, 12, 13 }, { 21, 22, 23 } };
const auto psi2DPointer = reinterpret_cast<const char*>(si2DArray);
for(auto i = 0U; i < size(si2DArray); ++i) {
for(auto j = 0U; j < size(*si2DArray); ++j) {
cout << *reinterpret_cast<const short*>(psi2DPointer + i * sizeof(*si2DArray) + j * sizeof(**si2DArray)) << '\t';
}
cout << endl;
}
请注意,在此示例中,即使我通过psi2DPointer
引用si2DArray
,我仍然使用来自si2DArray
的信息进行索引,即:
size(si2DArray)
size(*si2DArray)
sizeof(*si2DArray)
sizeof(**si2DArray)
char*
才被reinterpret_cast
认为是定义行为:http://en.cppreference.com/w/cpp/language/reinterpret_cast#Type_aliasing。Activity solution[a][b];
Activity* solutionPtrs[a];
for (int i = 0; i < a; ++i)
solutionPtrs[a] = solution[a];
Activity** mother = solutionPtrs;
T
的二维数组强制转换为 T**
呢?这是因为它们之间没有任何关系!T[a]
强制转换为 T*
,因为你得到的是指向该数组第一个元素的指针。T[a][b]
,那么它会衰减为 (T[b])*
,因为二维数组不是指针数组,而是数组的数组。solutionPtrs[a] = solution[a];
应该改为 solutionPtrs[i] = solution[i];
。 - jcchuks不确定您是否正在寻找类似于此的内容。您应该提供更多关于您想要实现的细节。它们是根本不同的类型。一种解决方案如下。
记录一下,如果有人觉得有用:
// define matrix
double A[3][3] = {
{ 1, 2, 3},
{ 4, 5, 6},
{ 7, 8, 9}
};
// allocate memory
double ** A_ptr = (double **) malloc(sizeof (double *) * 3);
for (int i = 0; i < 3; i++)
A_ptr[i] = (double *) malloc(sizeof (double) * 3);
// copy matrix
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
A_ptr[i][j] = A[i][j];
printf(" %f ", A_ptr[i][j]);
}
}
你不可以。它们是根本不同的类型。