从C ++中的函数返回数组

时间:2015-12-01 00:44:55

标签: c++ arrays pointers accelerometer gyroscope

美好的一天:)我正在研究一种用于从加速度计和陀螺仪获得俯仰角,偏航角和滚转角的代码。为了创建一个易于理解的更清晰的代码,我使用了两个不同的功能。一个用于计算俯仰偏转和俯仰的陀螺仪,另一个用于加速度计也可以做同样的事情。

float *readGyro(){
    /*get data from sensor here*/
    float gyroAngles[4]={gyroPitch,gyroRoll,gyroYaw};
    float* gyroPRY=gyroAngles;
    return gyroPRY;
}

float *readAccel(){
    /*get data from sensor here*/
    float accelAngles[4]={accelPitch,accelRoll,accelYaw};
    float* accelPRY=accelAngles;
    return accelPRY;
}

如上所示,我将函数的输出存储到一个数组中以传递给main函数。基本上指针被传递。但是,在从传递的指针访问值时,会打印常量垃圾值(不会随着我移动IMU而改变)(例如,2.38221e-44和-3.84146e-06)。我通过打印这些函数中的值来检查陀螺仪和加速度计的功能输出,它们很好。

int main(void){
    float *accelData;
    float *gyroData;

    while(1){
    accelData=readGyro();
    gyroData=readAccel();

    float accelPitch=*(accelData);
    float accelRoll=*(accelData+1);
    float accelYaw=*(accelData+2);

    float gyroPitch=*(gyroData);
    float gyroRoll=*(gyroData+1);
    float gyroYaw=*(gyroData+2);

    cout << "AccelPitch=" << accelPitch <<endl;
    cout << "AccelRoll=" << accelRoll <<endl;
    cout << "AccelYaw=" << accelYaw <<endl;
    cout << "GyroPitch=" << gyroPitch <<endl;
    cout << "GyroRoll=" << gyroRoll <<endl;
    cout << "GyroYaw=" << gyroYaw <<endl;

    }
}

我无法找到我的代码错误。在此之前,我咨询了许多参考文献。但是我仍然无法解决它。非常感谢您的帮助:)

4 个答案:

答案 0 :(得分:5)

C ++的内置数组是从C继承而来的,并不像大多数人期望的那样工作。让我们说你有这样的功能:

float* get_vec() {
    float vec[3] = { 1.0f, 2.0f, 3.0f };
    return vec;
}

实际上做的是返回堆栈分配变量vec地址;不幸的是,当函数结束时,vec将超出范围,返回的地址将毫无意义。

绕过这个方法是将数组包装在struct中,可以按值返回。您可以定义自己的,也可以使用C ++标准库中的std::array,如下所示:

std::array<float, 3> get_vec() {
    std::array<float, 3> vec = { 1.0f, 2.0f, 3.0f };
    return vec;
}

答案 1 :(得分:3)

你正在做的是返回函数本地数组的地址,该函数在函数退出时被销毁。

如果您想要一个数组用于建立索引,那么我建议您使用std::array

std::array<float, 3> readGyro() {
    /*get data from sensor here*/
    return {gyroPitch, gyroRoll, gyroYaw};
}

但更好的方法是使用这样的struct

struct angles
{
    float pitch;
    float roll;
    float yaw;
};

angles readGyro() {
    /*get data from sensor here*/
    return {gyroPitch, gyroRoll, gyroYaw};
}

答案 2 :(得分:1)

当你将指针返回readGyroreadAccel的堆栈时,你正在做的事情永远不会奏效。当这些函数退出时,堆栈的该部分将被回收,并且您将留下未定义的行为。

一种方法是分配数组并将其返回,但是你也必须自己也必须删除该分配。

您可以为所需参数创建2个结构并将它们传递给您的函数。这样,函数可以在返回后继续写入某个地方。

e.g。

#include <iostream>

using std::cout;
using std::endl;

struct gyro_data_t
{
    float pitch;
    float roll;
    float yaw;
};

struct accel_data_t
{
    float pitch;
    float roll;
    float yaw;
};

void readGyro(gyro_data_t* gd)
{
    /*get data from sensor here*/
    gd->pitch = 1.0f;
    gd->roll = 1.1f;
    gd->yaw = 1.2f;
}

void readAccel(accel_data_t* ad)
{
    /*get data from sensor here*/
    ad->pitch = 1.0f;
    ad->roll = 1.1f;
    ad->yaw = 1.2f;
}

int main(void)
{
    accel_data_t accelData;
    gyro_data_t gyroData;

    while(1)
    {
        readGyro(&gyroData);
        readAccel(&accelData);

        cout << "AccelPitch=" << accelData.pitch << endl;
        cout << "AccelRoll=" << accelData.roll << endl;
        cout << "AccelYaw=" << accelData.yaw << endl;
        cout << "GyroPitch=" << gyroData.pitch << endl;
        cout << "GyroRoll=" << gyroData.roll << endl;
        cout << "GyroYaw=" << gyroData.yaw << endl;
    }
}

请注意,这比示例更具可读性,因为它明确命名每个变量,而不是将它们表示为返回值的偏移量。不再需要赋予新变量以便理解值的含义。

这两个结构实际上是相同的,因此如果需要可以压缩成一个通用结构。

答案 3 :(得分:1)

将数组换行为按值返回的结构

将数组复制为数据成员时,将逐个复制数组元素,而不是复制衰减的指针。这样可以避免返回局部变量的地址。

foreach (TreeNode tn in tvPermission.Nodes)
    tn.Checked = (role.AccessPages.Where(p => p.Url == tn.Value).ToList().Count() > 0);

但是使用struct float3{ float fs[3]; }; float3 readGyro(){ float3 f3 = {}; f3.fs[0] = gyroPitch; f3.fs[1] = gyroRoll; f3.fs[2] = gyroYaw; return f3; } 作为其他答案说是非常合适的。你不需要发明另一个轮子。

通过引用

获取结果

如果您希望通过参数获取结果,请使用引用而不是指针来避免丢失大小信息(衰减到指针)。这也确保只传递std::array<float, 3>类型。

float[3]