Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: changes to examples to match new coding guidelines

...

Code Block
bgColor#FFCCCC
langc
#include <assert.h>
 
void func(void) {
  char c = 'x';
  int *ip = (int *)&c; /* This can lose information */
  char *cp = (char *)ip;
  assert(cp == &c);    /* Will fail on some conforming implementations */

  /* ... */
}

On some implementations, cp will not match &c. As a result, if a pointer to one object type is converted to a pointer to a different object type, the second object type must not require stricter alignment than the first.

...

Code Block
bgColor#FFCCCC
langc
char *loop_ptr;
int *int_ptr;

int *loop_function(void *v_pointer) {
  /* ... */
  return v_pointer;
}
 
void func(void) {
  int_ptr = loop_function(loop_ptr);

  /* ... */
}

This example compiles without warning. However, v_pointer can be aligned on a 1-byte boundary.

...

Code Block
bgColor#ccccff
langc
int *loop_ptr;
int *int_ptr;

int *loop_function(int *v_pointer) {
  /* ... */
  return v_pointer;
}
 
void func(void) {
  int_ptr = loop_function(loop_ptr);

  /* ... */
}

Another solution is to ensure that loop_ptr points to an object returned by malloc() because this object is guaranteed to be aligned properly for any need. However, this subtlety is easily missed when the program is modified in the future. It is easier and safer to let the type system document the alignment needs.

...

Code Block
bgColor#FFCCCC
langc
#include <string.h>
 
void func(void) {
  char *data;
  struct foo_header *tmp;
  struct foo_header *header;

  tmp = data + offset;
  memcpy(&header, tmp, sizeof(header));

  if (header.len < FOO) {
    /* ... */

  }
}

Unfortunately, the behavior is undefined when you assign an unaligned value to a pointer that points to a type that needs to be aligned. An implementation may notice, for example, that tmp and header must be aligned, so it could use an inlined memcpy() that uses instructions that assume aligned data.

...

Code Block
bgColor#ccccff
langc
#include <string.h>
 
char *data;
struct foo_header header;

void func(void) {
  memcpy(&header, data + offset, sizeof(header));

  if (header.len < FOO) {
    /* ... */

  }
}

Noncompliant Code Example

...

Code Block
bgColor#FFCCCC
langc
#include <assert.h>
 
void func(void) {
  char c = 'x';
  int *ip = (int *)&c; /* This can lose information */
  char *cp = (char *)ip;
  assert(cp == &c);    /* Will fail on some conforming implementations */

  /* ... */
}

Compliant Solution

This compliant solution uses alignas to align the the character c to the alignment of an integer. As a result, the two pointers point to equally aligned pointer types:

Code Block
bgColor#ccccff
langc
#include <stdalign.h>  /* For alignas() */
#include <assert.h>
 
void func(void) {
  alignas(int) char c = 'x'; /* Align c to the alignment of an int */
  int *ip = (int *)&c; 
  char *cp = (char *)ip;
  assert(cp == &c);    /* Both cp and &c point to equally aligned objects */
  /* ... */
}

Risk Assessment

Accessing a pointer or an object that is no longer on the correct access boundary can cause a program to crash or give wrong information, or it can cause slow pointer accesses (if the architecture allows misaligned accesses).

...