0

According to:

MISRA C-2012 Rule 11.3 violation while trying to do a typecast from char to int pointer

below piece of code is violating strict aliasing rule but what I'm missing here is what could compiler do wrong in such example that the result would be unexpected/undefined? Also no warning from compiler about any issue.

// compiled with -fstrict-aliasing -Wstrict-aliasing=2 -O3 -std=c99
uint8_t buffer[4];

static uint32_t get_word(uint8_t *cp)
{
    return *((uint32_t *)cp);
}

int main()
{
    buffer[0] = 8;
    printf("value: %u", get_word(buffer));
    return 0;
}

Let's not talk why I want to convert buffer of 4 chars to a word like that(instead of shifting) but rather why is this a problem at all and if there are cases where violating this rule will not get me into trouble.

akimata
  • 131
  • 1
  • 7
  • 1
    `buffer` may not be correctly aligned for a `uint32_t` – Support Ukraine Feb 05 '23 at 11:41
  • As I have recently come to understand it, the main aliasing problem is that undefined behaviour is undefined, so the compiler can legally do anything. Supposing it tried to interpret correctly, it can still cause problems because the optimiser might reorder instructions in a way that breaks the logic. It assumes for example, that an int is not altered when a float is altered. In your code however, I think it would be okay because uint8_t is treated like unsigned char which is treated differently from longer types. I'm happy to be corrected about this as I'm keen to get this stuff right myself. – Simon Goater Feb 05 '23 at 11:41
  • 1
    OT: `%u` is not the correct portable way to print `uint32_t` – Support Ukraine Feb 05 '23 at 11:44
  • The problem is that the compiler, especially optimizing compiler, can become utterly confused, that's what. Instead of pondering this, just use the standard solution, `memcpy`. – HolyBlackCat Feb 05 '23 at 11:50
  • So the golden rule while using strict aliasing would be to never use/cast a pointer of uncompatible type? – akimata Feb 05 '23 at 12:09
  • For example, the compiler could deduce that `buffer` is never read from, so omit its initializer. It could deduce that the `printf` statement is never executed because it would UB if it did, so omit that. Obviously these optimizations look ridiculous, but that's what UB opens up and why we avoid it. – Paul Hankin Feb 05 '23 at 12:23
  • 1
    I think your golden rule is right with the exception of assigning a (unsigned) char pointer to any pointer is okay. The converse however, is not okay. You can put buffer in a union with an int for c99 and later for legal 'type-punning'. – Simon Goater Feb 05 '23 at 13:06

0 Answers0