I'm trying to assemble information in a struct to later memcopy it to an spi buffer. This is the code I'm working with:
#include <cstdio>
#include <cstdint>
#include <cstring> /* memcpy */
using data_settings = uint8_t;
enum class channel_settings : uint8_t
{
power_down_setting = 0,
DA1,
DA2,
DA3,
DA4,
DA5,
DA6,
DA7,
DA8,
power_down_release,
NA1,
NA2,
io_da_select,
io_serial_parallel,
io_parallel_serial,
io_status_setting,
};
struct message
{
data_settings data;
channel_settings channel;
};
int main()
{
message m = { 255, channel_settings::DA5 };
uint32_t spi_buf;
std::memcpy(&spi_buf, &m, 4);
printf("sizeof m = %zu, spi_buf = %#010x\n", sizeof(message), spi_buf);
}
But gcc 12 x86 spits out the following warning:
<source>:38:16: warning: 'void* memcpy(void*, const void*, size_t)' forming offset [2, 3] is out of the bounds [0, 2] of object 'm' with type 'message' [-Warray-bounds=]
38 | std::memcpy(&spi_buf, &m, 4);
| ~~~~~~~~~~~^~~~~~~~~~~~~~~~~
<source>:35:13: note: 'm' declared here
35 | message m = { 255, channel_settings::DA5 };
| ^
What is the issue here? Are there alignement concerns as my struct is only 2 bytes?
The output is as follows:
sizeof m = 2, spi_buf = 0x000005ff
And it seems that the data settings will occupy the less significant byte which is actually what I'm looking for. However, what happens if the system is big endian? How can I write my struct endian-independent so that memcopied data will always reflect the same bit ordering?