我有一个函数,它接受一个指向浮点数组的指针。根据其他条件,我知道指针实际上指向 2x2 OR 3x3 矩阵。 (事实上,内存最初是这样分配的,例如 float M[2][2] )重要的是我想在函数体中做出这个决定,而不是作为函数参数。
void calcMatrix( int face, float * matrixReturnAsArray )
{
// Here, I would much rather work in natural matrix notation
if( is2x2 )
{
// ### cast matrixReturnAsArray to somethingAsMatrix[2][2]
somethingAsMatrix[0][1] = 2.002;
// etc..
}
else if(is3x3)
{ //etc...
}
}
我知道我可以使用模板和其他技术来更好地解决这个问题。我的问题实际上是关于如何在 ### 评论中进行这样的转换。使用 C++ 工作。
float (*somethingAsMatrix)[2] = (float (*)[2]) matrixReturnAsArray;
float *
可以指向浮点数组的第一个元素,并且应该可以重新解释到该数组类型。该转换的结果可能指向 float [][]
的第一个元素,因此应该可以reinterpret_castable 到该类型,依此类推。您应该能够编写这样的演员表并直接执行
float (&arr)[2][2] = *reinterpret_cast<float (*)[2][2]>(matrixReturnAsArray);
float **
类型的参数不同,不应该这样使用。
为了避免未定义的行为,指针必须源自实际的多维数组,如果直接使用
float*
,则无法访问多维矩阵的第一行。
void foo(float *f) {
f[3] = 10.;
float (&arr)[2][2] = *reinterpret_cast<float (*)[2][2]>(f);
arr[1][1] = 10.;
}
void main() {
float a[2][2];
foo(&a[0][0]); // f[3] = 10.; is undefined behavior, arr[1][1] = 10. is well defined
float b[4];
foo(&b[0]); // f[3] = 10.; is well-defined behavior, arr[1][1] = 10. is undefined
}
鉴于
float arr[2][2];
,据我所知,没有任何东西可以保证 &arr[0][1] + 1
与 &arr[1][0]
相同。因此,尽管您可以通过执行 f[i*width + j]
将一维数组用作多维数组,但您不能将多维数组视为单维数组。
最好使用 C++ 的编译时类型安全性,而不是仅仅依赖于不意外地传递错误的东西或执行错误的reinterpret_cast。要使用原始数组获得类型安全,您应该使用对所需原始数组类型的引用:
void foo(float (&f)[2][2]) {}
void foo(float (&f)[3][3]) {}
如果你想按值传递数组,你不能使用原始数组,而应该使用 std::array:
void foo(std::array<std::array<float,2>,2> f) {}
void foo(std::array<std::array<float,3>,3> f) {}
通过明智地使用 typedef,这种类型的转换总是更干净、更容易处理:
typedef float Matrix_t[2][2];
Matrix_t* someThingAsMatrix = (Matrix_t*) matrixReturnAsArray;
如果这是 C++ 而不是 C,那么您应该创建一个矩阵类。 (或者更好的是,寻找一个开源的。)
如果我是对的:
typedef float Matrix_t[2][2];
Matrix_t &matrix = *(Matrix_t *)matrixReturnAsArray;
或
float (&matrix2)[2][2] = *(float ( *)[2][2])matrixReturnAsArray;
在C中只有指针的方式
Matrix_t *someThingAsMatrix = (Matrix_t *)matrixReturnAsArray;
并通过以下方式访问:
(*someThingAsMatrix)[1][0] = ...