如何将 std:array<char> 的结构转换为单个 std::array<char>

How to cast struct of std:array<char> to single std::array<char>

提问人:Typhaon 提问时间:10/18/2022 更新时间:10/18/2022 访问量:92

问:

我正在打包要发送到另一台设备的消息。我正在使用 C++11。通常有效负载是单个 ASCII 编码值,但这个命令的参数更多一些。我正在尝试将有效负载打包到单个字符数组中。我正在寻找一个干净的解决方案,我认为以下(示例)解决方案应该有效:

Message foo(Parameters parameters) {
    struct __attribute__((__packed__)) ParameterPayload {
        std::array<char,2> a;
        std::array<char,2> b;
        std::array<char,2> c; 
        std::array<char,4> d;
    }; // Actual struct has way more parameters
    ParameterPayload paramPayload;
    paramPayload.a = bar<2,10>(parameters.a);
    paramPayload.b = bar<2,10>(parameters.b);
    paramPayload.c = bar<2,10>(parameters.c);
    paramPayload.d = bar<4,16>(parameters.d);
    
    // This will not work, but I want something like this to work
    auto payload =  reinterpreted_cast<std::array<char, sizeof(ParameterPayload)>(paramPayload);

    return baz<sizeof(ParameterPayload)>(payload);
}

template<size_t size, int base>
std::array<char, size> bar(int input> {
    // ASCII encoding with a base (2, 10 or 16)
}

template<size_t payloadSize>
Message baz(std::array<char, payloadSize> payload) {
    // Some packing computation
}

这是一个粗略的例子,但我认为它会传达信息。如何将结构转换为单个 std:array<char, N>?甚至可能吗?我尽量不做多个 std::copys,因为这会花费更多资源并会降低可读性。

我研究的另一个解决方案是使用

const char* const payload = reinterpret_cast<const char* const>(&paramPayload);

然后从那里开始......在那之后,我可以做一个副本,但我想避免它。

C++ 数组 C++11 强制转换 STD

评论

0赞 463035818_is_not_an_ai 10/18/2022
相关 stackoverflow.com/questions/69500721/...

答:

1赞 Jarod42 10/18/2022 #1

这种转换是迂腐的 UB(甚至我们无法保证 std::array 的确切大小)。

我建议改成这样:

Message foo(Parameters parameters) {
    std::array<char, 2+2+2+4> payload; // Actual struct has way more parameters
    int offset = 0;
    bar<2, 10>(parameters.a, payload.data() + offset, offset);
    bar<2, 10>(parameters.b, payload.data() + offset, offset);
    bar<2, 10>(parameters.c, payload.data() + offset, offset);
    bar<4, 16>(parameters.d, payload.data() + offset, offset);

    return baz(payload);
}

template<size_t size, int base>
void bar(int input, char* out, int& offset) /* std::span<char, size> out (in C++20) */
{
    offset += size;
    // ASCII encoding with a base (2, 10 or 16)
}

template<size_t payloadSize>
Message baz(std::array<char, payloadSize> payload) {
    // Some packing computation
}