Search code examples
cstructcrc16

How to compute a crc16 on a struct


I recently read some papers and code on crc computation (e.g. A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS and the implementation in Linux). As far as I understand, crc is done byte by byte starting on a certain address.

example from Linux Kernel:

u16 crc16(u16 crc, u8 const *buffer, size_t len)
{
    while (len--)
    crc = crc16_byte(crc, *buffer++);
    return crc;
}

Now I am asking myself is it possible to do this easily with a struct?


Solution

  • Not in general if you want a sensible result, no.

    This is because CRC is supposed to be computed over a sequence of "known" bytes, and a structure in memory is not a sequence of known bytes. There can be padding bytes for alignment purposes, which you do not necessarily know about or have control over, and of course various fields can have various sizes (as can the struct itself) on different systems/platforms.

    If you first can serialize the struct to a sequence of bytes with a known and stable mapping, then of course you can apply CRC to that sequence. This is (subtly) hinted at by the buffer argument being const u8 *, i.e. pointer to constant byte, and not const void *.

    If you don't care, and don't mind breaking if (for instance) you change the compiler settings and/or move the program to a different system, you could just use:

    const struct mystruct s = { ... };
    const u16 crc = crc16(0, (u8 *) &s, sizeof s);
    

    But this will include any padding in the struct, so it's very dangerous.