Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Modifying a variable through a pointer of an incompatible type (other than unsigned char) can lead to unpredictable results. This problem is often caused by a violation of aliasing rules. The C Standard, Section subclause 6.5, paragraph 7 [ISO/IEC 9899:2011], specifies those circumstances in which an object may or may not be aliased.

...

In this noncompliant example, a diagnostic is required because an object of type float is incremented through a pointer to int, ip:

...

The programmer in this noncompliant code example is attempting to read from a different union member than the one most recently written to; this , which is known as type-punning:

Code Block
bgColor#FFCCCC
langc
union a_union {
  int i;
  double d;
};

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

However, instead of reading directly from the union member, it assigns a pointer, ip, to reference the integer value and returns the value referenced by the pointer. Unfortunately, this is a violation of the strict aliasing rules, and in this case, the compiler may determine that ip refers to some value other than the value stored by t.i and return a value other than the expected value.

...

In this noncompliant code example, access by taking the address, casting the resulting pointer, and dereferencing the result has undefined behavior , even if the cast uses a union type:

Code Block
bgColor#FFCCCC
langc
union a_union {
  int i;
  double d;
};

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

...

Code Block
bgColor#FFCCCC
langc
short a[2];

a[0]=0x1111;
a[1]=0x1111;

*(int *)a = 0x22222222;  /* violationViolation of aliasing rules */

printf("%x %x\n", a[0], a[1]);

...

In this example, a gadget object is allocated, then realloc() is called to create a widget object using the memory from the gadget object.   While Although reusing memory to change types is acceptable, accessing the memory copied from the original object is undefined behavior.

...

This compliant solution reuses the memory from the gadget object , but re-initializes reinitializes the memory to a consistent state before reading from it.:

Code Block
bgColor#ccccff
langc
#include <stdlib.h>
#include <string.h>
 
struct gadget {
  int i;
  double d;
  char *p;
};
 
struct widget {
  char *q;
  int j;
  double e;
};
 
struct gadget *gp;
struct widget *wp;
 
gp = (struct gadget *)malloc(sizeof (struct gadget));
if (!gp) {
  /* Handle error */
}
/* ... */
wp = (struct widget *)realloc(gp, sizeof(struct widget));
if (!wp) {
  free(gp);
  /* Handle error */
}
memset(wp, 0, sizeof(struct widget));
if (wp->j == 12) {
  /* ... */
}

...

[Acton 2006]"Understanding Strict Aliasing"
GCC Known Bugs"C Bugs, Aliasing Issues while Casting to Incompatible Types"
GCC Manual 
[ISO/IEC 9899:2011]Section Subclause 6.5, "Expressions"
[Walfridsson 2003]Aliasing, Pointer Casts and GCC 3.3

...