如何用数组初始化结构?

时间:2019-12-06 08:11:28

标签: c++ arrays pointers struct initialization

有没有比以下方法更好的初始化带有数组的结构的方法?

struct Parameters
{
    double distance;
    double radius;
    double strength;
    long distanceX;
    long distanceY;
    long clickX;
    long clickY;
};

void calculate(double dParameters[], long lParameters[])
{
    Parameters param = 
    {
        dParameters[0], 
        dParameters[1],
        dParameters[2],

        lParameters[0],
        lParameters[1],
        lParameters[2],
        lParameters[3]
    };
}

我想到了分配指针:

void calculate(double dParameters[], long lParameters[])
{
    Parameters param;
    (double*)(&param.distance) = &dParameters[0];
    (long*)(&param.distanceX) = &lParameters[0];
}

但是我确定它在c ++中是否有效。

2 个答案:

答案 0 :(得分:0)

您的第二个示例是非法的,但是优化器(知道实际的布局)确实会像这样实现它。

答案 1 :(得分:0)

如果您知道该结构的布局,并且已经精心选择将所有类似类型的成员按顺序放置,而它们之间没有任何东西,那么您可以使用memcpy()

memcpy(&param.distance, dParameters, sizeof(*dParameters) * 3);
memcpy(&param.distanceX, lParameters, sizeof(*lParameters) * 4);

这是相当脆弱的代码,因为distance必须是连续四个正好是双精度参数的第一个双精度参数,否则您将得到损坏的数据,并且在编译时不会对此进行验证。

可以使用offsetof进行改进以获取和/或验证长度。如:

void calculate(double dParameters[], size_t n_dParameters, long lParameters[], size_t n_lParameters)
{
    Parameters param;

    assert(offsetof(Parameters, strength) - offsetof(Parameters, distance) == sizeof(*dParameters) * n_dParameters);
    memcpy(&param.distance, dParameters, offsetof(Parameters, strength) - offsetof(Parameters, distance));
    assert(offsetof(Parameters, clickY) - offsetof(Parameters, distanceX) == sizeof(*lParameters) * n_lParameters);
    memcpy(&param.distanceX, dParameters, offsetof(Parameters, clickY) - offsetof(Parameters, distanceX));
}

从历史上看,gcc在优化结构初始化方面并不擅长,例如在可能且有益的情况下使用等效的memcpy()memset()。如果您的结构有一百个字段,那么这实际上可能会有用。

另一种技术将用于联合,以定义结构的数组版本和单个字段版本。

struct ParametersArrays {
   double doubles[3];
   long longs[4];
};
union ParametersUnion {
   struct Parameters params;
   struct ParametersArrays arrays;
};
ParametersUnion u;
memcpy(u.arrays.doubles, dParameters, sizeof(u.arrays.doubles));
memcpy(u.arrays.longs, lParameters, sizeof(u.arrays.longs));
Parameters& p = u.params; // Now you can use p

请注意,在C ++中使用这样一个联合体中的多个成员并不是严格合法的,但在C中是合法的,大多数/所有C ++编译器都会按预期进行编译。