Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Warning: cast increases required alignment

I'm recently working on this platform for which a legacy codebase issues a large number of "cast increases required alignment to N" warnings, where N is the size of the target of the cast.

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

Hopefully it's obvious that a "real" implementation would be a bit more complex, but the basic point is that I've got data coming from somewhere, I know that it's aligned (because I need the id and type to be aligned), and yet I get the message that the cast is increasing the alignment, in the example case, to 4.

Now I know that I can suppress the warning with an argument to the compiler, and I know that I can cast the bit inside the parentheses to void* first, but I don't really want to go through every bit of code that needs this sort of manipulation (there's a lot because we load a lot of data off of disk, and that data comes in as char buffers so that we can easily pointer-advance), but can anyone give me any other thoughts on this problem? I mean, to me it seems like such an important and common option that you wouldn't want to warn, and if there is actually the possibility of doing it wrong then suppressing the warning isn't going to help. Finally, can't the compiler know as I do how the object in question is actually aligned in the structure, so it should be able to not worry about the alignment on that particular object unless it got bumped a byte or two?

like image 629
dash-tom-bang Avatar asked Apr 30 '10 01:04

dash-tom-bang


1 Answers

One possible alternative might be:

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

For x86 architecture, the alignment isn't going to matter that much, it's more a performance issue that isn't really relevant for the code you have provided. For other architectures (eg MIPS) misaligned accesses cause CPU exceptions.


OK, here's another alternative:

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

Here's variation on the above that includes the suggestions from 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
}
like image 125
clstrfsck Avatar answered Sep 22 '22 00:09

clstrfsck