Как написать функцию, возвращающую матрицу?

Мне нужна функция, возвращающая матрицу вращения 2x2, что-то вроде:

float matrix(float phi){
  float R[2][2] = { {cos(phi), -sin(phi)}, 
                    {sin(phi),  cos(phi)} };
return R;
}

Очевидно, это не работает. Как лучше всего написать эту функцию?

, 👍0


2 ответа


Лучший ответ:

-1

Один из способов — заставить функцию возвращать указатель с плавающей запятой, т.е. создать новый массив и вернуть его

float** matrix(float phi){
   float** R= (float **)malloc(2 * 2 * sizeof(float));
   R[0][0]= cos(phi);
   R[0][1]= -sin(phi);
   R[1][0]= sin(phi);
   R[1][1]= cos(phi);
   return R;
}

Не забудьте освободить память, если она вам больше не нужна!

Однако я бы посоветовал вам не делать этого, а передать массив в функцию. См. Как объявить массив переменного размера (глобально) и Использует malloc() и free() - действительно плохая идея для Arduino? для объяснения, почему выделение памяти в функции может быть не очень хорошей идеей (во встроенной среде, известной как Arduino)

,

Это не то, как вы создаете 2D-массив. Здесь R[0] и R[1] — это неинициализированные указатели float *, а R[0][0] — это разыменование одного такого указателя. Это неопределенное поведение может привести к сбою программы., @Edgar Bonet

Ух ты... C++ слишком сложно программировать., @2012User

@ Эдгар Боне, как мне написать эту функцию?, @2012User


1

Вы не можете вернуть массив из функции. Есть несколько альтернативы, однако. Один из них — выделить память для массив внутри функции, как предложено в ответе пользователя2912328. Я бы однако не рекомендую этот подход по причинам, уже указанным в этот ответ.

Обзор других возможных вариантов см. в этом ответе на вопрос «Возврат целочисленного массива из функции».

Теперь ваша проблема немного другая, поскольку у вас есть 2D-массив. Синтаксис C/C++ для решения этих задач сложен, но начнем.

Если вы выберете решение «статический массив» (убедитесь, что вы понимаете последствия), вы могли бы написать:

float (*matrix(float phi))[2]
{
    static float R[2][2];
    R[0][0] = cos(phi);
    R[0][1] = -sin(phi);
    R[1][0] = sin(phi);
    R[1][1] = cos(phi);
    return R;
}

и вы бы использовали его так:

float (*M)[2] = matrix(angle);

Если вместо этого вы позволите вызывающему объекту управлять распределением, то

float (*matrix(float phi, float (*R)[2]))[2]
{
    R[0][0] = cos(phi);
    R[0][1] = -sin(phi);
    R[1][0] = sin(phi);
    R[1][1] = cos(phi);
    return R;
}

Или можно отказаться от возвращаемого значения, чтобы упростить синтаксис:

void matrix(float phi, float (*R)[2])
{
    R[0][0] = cos(phi);
    R[0][1] = -sin(phi);
    R[1][0] = sin(phi);
    R[1][1] = cos(phi);
}

и вы можете использовать его так:

float M[2][2];
matrix(angle, M);

Решение «массив в структуре» более простое.

Если вас беспокоит синтаксис работы с 2D-массивами (это будет понятно), вместо этого вы можете использовать массивы указателей на одномерные массивы. С этим легче справиться, но сложнее распределить. Этот подход мог бы потребовать другого ответа...


Изменить. Один из распространенных способов упростить синтаксис запутанного массива — использовать определения типов. Поскольку идентификатор массива 2x2 превращается в указатель на массив из двух чисел с плавающей запятой, вы можете назвать этот тип:

typedef float (*pmatrix)[2];  // указатель на массив из двух чисел с плавающей запятой

Тогда вместо

float (*matrix(float phi))[2] { ... }
...
float (*M)[2] = matrix(angle);

вы бы написали

pmatrix matrix(float phi) { ... }
...
pmatrix M = matrix(angle);
,