简体   繁体   English

如何用数组初始化结构体?

[英]How to initialize struct with an array?

Is there a better way of initializing a struct with an array than doing the following?有没有比执行以下操作更好的用数组初始化结构的方法?

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]
    };
}

I thought of assigning pointers:我想到了分配指针:

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

But I am not sure if it is valid in c++.但我不确定它在 C++ 中是否有效。

If you know the layout of the struct, and have carefully chosen to put all members of like type in order without anything between them, then you could use memcpy() .如果您知道结构的布局,并且仔细选择将所有同类成员按顺序排列,而它们之间没有任何东西,那么您可以使用memcpy()

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

This is rather fragile code, as distance must be the first double parameter of exactly four double parameters in a row, or you'll get corrupted data, and nothing will verify this at compile time.这是相当脆弱的代码,因为distance必须是连续四个双参数中的第一个双参数,否则您将获得损坏的数据,并且在编译时无法验证这一点。

It could be improved with offsetof to get and/or verify the length.可以使用offsetof改进以获取和/或验证长度。 Such as:如:

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));
}

Historically, gcc has not been great at optimizing struct initialization, such as using the equivalent of memcpy() or memset() when it would be possible and beneficial.从历史上看,gcc 在优化结构体初始化方面并不是很好,例如在可能且有益的情况下使用memcpy()memset()的等效项。 If your struct had a hundred fields, this might actually be useful.如果您的结构有一百个字段,这实际上可能很有用。

Another technique would be use to a union to define both an array version and an individual field version of your struct.另一种技术是使用联合来定义结构的数组版本和单个字段版本。

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

Note that using more than one member of a union like this is not strictly legal in C++, but it is in C, and most/all C++ compilers will compile it as expected.请注意,像这样使用多个联合成员在 C++ 中不是严格合法的,但在 C 中是合法的,并且大多数/所有 C++ 编译器都会按预期编译它。

你的第二个例子是非法的,但优化器(知道实际布局)确实像那样实现了它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM