Pointer aliasing is a common pitfall:

warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]

From gcc man page:

-fstrict-aliasing

Allow the compiler to assume the strictest aliasing rules applicable to the language being compiled. For C (and C++), this activates optimizations based on the type of expressions. In particular, an object of one type is assumed never to reside at the same address as an object of a different type, unless the types are almost the same. For example, an “unsigned int” can alias an “int”, but not a “void*” or a “double”. A character type may alias any other type.

Pay special attention to code like this:

  union a_union {
      int i;
      double d;
  };

  int f() {
      union a_union t;
      t.d = 3.0;
      return t.i;
  }

The practice of reading from a different union member than the one most recently written to (called “type-punning”) is common. Even with -fstrict-aliasing, type-punning is allowed, provided the memory is accessed through the union type. So, the code above works as expected. However, this code might not:

  int f() {
      union a_union t;
      int* ip;
      t.d = 3.0;
      ip = &t.i;
      return *ip;
  }

Similarly, access by taking the address, casting the resulting pointer and dereferencing the result has undefined behavior, even if the cast uses a union type, e.g.:

  int f() {
      double d = 3.0;
      return ((union a_union *) &d)->i;
  }

The -fstrict-aliasing option is enabled at levels -O2, -O3, -Os.

StackOverflow threads: