29

浮動小数点配列へのポインターを受け取る関数があります。他の条件に基づいて、ポインターが実際に2x2または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 *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];ことを保証するものは何もありません。したがって、1次元配列を多次元配列として使用することはできますが、多次元配列を1次元配列のように扱うことはできません。&arr[0][1] + 1&arr[1][0]f[i*width + j]

誤って間違ったものを渡したり、間違ったreinterpret_castを実行したりしないことに依存するのではなく、C++のコンパイル時の型安全性を使用することをお勧めします。raw-arraysを使用して型の安全性を得るには、必要なraw配列型への参照を使用する必要があります。

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 に答える