предупреждение: ISO C ++ запрещает массив переменной длины - PullRequest
0 голосов
/ 06 июня 2018

У меня есть функция, которая принимает указатель на массив с плавающей запятой.Основываясь на других условиях, я знаю, что указатель фактически указывает на матрицу 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...
    }

}

float (somethingAsMatrix)[2] = (float ()[2]) matrixReturnAsArray; 

это работает нормально.

здесь, если я хочу упомянуть значение в индексе как переменную, которая будет меняться в зависимости от некоторых условий.

Если я сделаю это, появится предупреждение: ISO C ++ запрещает массив переменной длины.Из этого, как я могу динамически создать что-то?

Ответы [ 3 ]

0 голосов
/ 06 июня 2018

Ниже показано, как выполнять приведение.

#include <stdio.h>

typedef float t2[2][2];
typedef float t3[3][3];

static void test(int is2, void * p)
{
    if(is2)
    {
        t2 *a = (t2 *)p;
        (*a)[1][1] = 1.23;
    }
    else
    {
        (*((t3*)p))[1][1] = 2.34;
    }
}

int main()
{
    printf("Hello World\n");
    t2 test2 = {{1,2},{3,4}};
    t3 test3 = {{1,2,3},{4,5,6},{7,8,9}};

    test(1,(void *)test2);
    printf("%g\n",test2[1][1]);

    test(0,(void *)test3);
    printf("%g\n",test3[1][1]);

    return 0;
}
0 голосов
/ 06 июня 2018

Вы можете передать массив по ссылке.

void calcMatrix(float (&matrix)[2][2])   // Only binds to 2*2 matrix
{
}
void calcMatrix(float (&matrix)[3][3])   // Only binds to 3*3 matrix
{
}

int main()
{
   float a[2][2] ={{1,2} , {3,4}};
   calcMatrix(a); 

   float b[3][3] ={{1,2,3} , {4,5,6}, {7,8,9}};
   calcMatrix(b); 
}

Если вам нужна функция, которая работает с переменными размерами, вы можете шаблонизировать ее:

template<int S>
void calcMatrix(float (&matrix)[S][S])   // Only binds to S*S matrix
{
}
0 голосов
/ 06 июня 2018

Массив в C ++ должен иметь размер, определенный во время компиляции.

Если вы хотите массив переменной длины, используйте вместо него std::vector.

В вашем случае я бы использовал шаблон для размера матрицы и имел бы другую реализацию для другого размера матрицы (если я не понял ваши намерения).

template<int SIZE> 
    struct Matrix {
    std::array<std::array<float, SIZE>,SIZE> m;
    std::array<float,SIZE>& operator[](int a) {
        if(a>=SIZE) {
            throw std::out_of_range("Out of range exception");
        }
        return m[a];
    }
};

template<int SIZE>
void calcMatrix(Matrix<SIZE>& matrixReturnAsArray );


template<>
void calcMatrix<2>(Matrix<2>& matrixReturnAsArray )
{
     // Code for 2x2 Matrix
    std::cout << "<2>" << std::endl;
    std::cout << matrixReturnAsArray[1][1] << std::endl;
}

template<>
void calcMatrix<3>(Matrix<3>& matrixReturnAsArray )
{
     // Code for 3x3 matrix
        std::cout << "<3>" << std::endl;
        std::cout << matrixReturnAsArray[2][2] << std::endl;
}

int main() {
   std::array<float,2> a={1,2};
   Matrix<2> m2;
   m2.m = {a,a};
   std::array<float,3> b={1,2,3};
   Matrix<3> m3;
   m3.m = {b,b,b};
   calcMatrix(m3); 
   calcMatrix(m2);
}

Поскольку я не определил универсальный шаблон, использование любого другого значения, кроме 2 или 3 для размера, приведет к ошибке во время компиляции.

Редактировать: Использовать ссылку на массив std :: вместо указателя после предложения @ Калет

Редактировать 2: Добавлен оператор [] для легкого доступа и исключения для безопасности

...