29

我有一个函数,它需要一个指向浮点数组的指针。基于其他条件,我知道指针实际上指向一个 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++ 工作。

4

3 回答 3

35
float (*somethingAsMatrix)[2] = (float (*)[2]) matrixReturnAsArray;
于 2012-08-08T16:41:19.453 回答
8

float *可以指向浮点数组的第一个元素,并且应该 reinterpret_castable 到该数组类型。并且该转换的结果可能指向 a 的第一个元素,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) {}
于 2012-08-08T17:04:12.587 回答
1

这种类型的转换总是更干净,更容易处理,明智地使用 typedef:

typedef float Matrix_t[2][2];

Matrix_t* someThingAsMatrix = (Matrix_t*) matrixReturnAsArray;

但是,如果这是 C++ 而不是 C,则应该创建一个矩阵类。(或者更好的是,寻找一个开源的。)

于 2012-08-08T16:50:12.213 回答