警告:施法增加了所需的对齐

das*_*ang 8 c++ compilation

我最近在这个平台上工作,遗留代码库会发出大量"强制转换需要对齐N"警告,其中N是演员目标的大小.

struct Message
{
   int32_t id;
   int32_t type;
   int8_t  data[16];
};

int32_t GetMessageInt(const Message& m)
{
   return *reinterpret_cast<int32_t*>(&data[0]);
}
Run Code Online (Sandbox Code Playgroud)

希望很明显,"真正的"实现会有点复杂,但基本的一点是我有来自某个地方的数据,我知道它是对齐的(因为我需要id和类型对齐),以及然而我得到的消息是,演员正在增加对齐,在示例中,为4.

现在我知道我可以用编译器的参数来抑制警告,我知道我可以先将括号中的位转换为void*,但我真的不想通过需要这个的所有代码一种操作(有很多因为我们从磁盘上加载了大量数据,并且这些数据以char缓冲区形式出现以便我们可以轻松地指针前进),但是有人能给我关于这个问题的任何其他想法吗?我的意思是,对我来说,似乎是一个非常重要和常见的选择,你不想要警告,如果实际上有可能做错了,那么抑制警告就没有用了.最后,编译器不能像我一样知道所讨论的对象是如何在结构中实际对齐的,所以它应该能够不担心该特定对象的对齐,除非它碰到了一个或两个字节?

msa*_*ord 4

一种可能的替代方案可能是:

int32_t GetMessageInt(const Message& m)
{
   int32_t value;
   memcpy(&value, &(data[0]), sizeof(int32_t));
   return value;
}
Run Code Online (Sandbox Code Playgroud)

对于 x86 架构,对齐并不那么重要,它更多的是一个与您提供的代码并不真正相关的性能问题。对于其他体系结构(例如 MIPS),未对齐的访问会导致 CPU 异常。


好的,这是另一种选择:

struct Message
{
    int32_t id;
    int32_t type;
    union
    {
        int8_t  data[16];
        int32_t data_as_int32[16 * sizeof(int8_t) / sizeof(int32_t)];
        // Others as required
    };
};

int32_t GetMessageInt(const Message& m)
{
    return m.data_as_int32[0];
}
Run Code Online (Sandbox Code Playgroud)

以下是上述内容的变体,其中包括以下建议cpstubing06

template <size_t N>
struct Message
{
    int32_t id;
    int32_t type;
    union
    {
        int8_t  data[N];
        int32_t data_as_int32[N * sizeof(int8_t) / sizeof(int32_t)];
        // Others as required
    };
    static_assert((N * sizeof(int8_t) % sizeof(int32_t)) == 0,
                  "N is not a multiple of sizeof(int32_t)");
};

int32_t GetMessageInt(const Message<16>& m)
{
    return m.data_as_int32[0];
}


// Runtime size checks
template <size_t N>
void CheckSize()
{
    assert(sizeof(Message<N>) == N * sizeof(int8_t) + 2 * sizeof(int32_t));
}

void CheckSizes()
{
    CheckSize<8>();
    CheckSize<16>();
    // Others as required
}
Run Code Online (Sandbox Code Playgroud)