...
A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to the referenced type, the behavior is undefined.
...
If the misaligned pointer is dereferenced, the program may terminate abnormally. The On some architectures, the cast alone may cause a loss of information even if the value is not dereferenced . For if the types involved have differing alignment requirements.
Noncompliant Code Example
In this noncompliant example, the
...
char pointer &c
is converted to the more strictly aligned int
pointer ip
. 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 | ||||
---|---|---|---|---|
| ||||
#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.
Noncompliant Code Example
...
assert(cp == &c);
}
|
Compliant Solution (Intermediate Object)
In this compliant solution, the char
value is stored into an int
so that the pointer's value will be properly aligned:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <assert.h> void ffunc(void) { char c int *i_ptr= 'x'; charint i = c; int i_ptr*ip = (int *)&c; /* Violation */i; /* ... */ } |
Compliant Solution
assert(ip == &i);
} |
Compliant Solution (C11, alignas()
)
This compliant solution uses alignas
to align the character c
to the alignment of an integer. As a result, the two pointers point to equally aligned pointer typesIn this compliant solution, the value referenced by the char
pointer c_ptr
has the alignment of type int
:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdalign.h> #include <assert.h> void ffunc(void) { char/* Align *c_ptr; c to the alignment of an int *i_ptr;/ alignas(int i) char c = 'x'; int c_ptr*ip = (charint *)⁣ char i_ptr*cp = (intchar *)c_ptrip; /* ... */ Both cp and &c point to equally aligned objects */ assert(cp == &c); } |
Noncompliant Code Example
...
Code Block | ||||
---|---|---|---|---|
| ||||
char *loop_ptr; int *int_ptr; int *loop_function(void *v_pointer) { /* ... */ return v_pointer; } void func(voidchar *loop_ptr) { int *int_ptr = loop_function(loop_ptr); /* ... */ } |
This example compiles without warning. However, v_pointer
can be aligned on a 1-byte boundarymore strictly aligned than an int *
.
Compliant Solution
Because the input parameter directly influences the return value, and loop_function()
returns an int *
, the formal parameter v_pointer
is redeclared to accept only int *
:
Code Block | ||||
---|---|---|---|---|
| ||||
int *loop_ptr; int *int_ptr; int *loop_function(int *v_pointer) { /* ... */ return v_pointer; } void func(voidint *loop_ptr) { int *int_ptr = loop_function(loop_ptr); /* ... */ } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <string.h> void func(void) { char *data;struct foo_header { int len; /* ... */ }; void func(char *data, size_t offset) { 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.
Compliant Solution
This compliant solution does not use the foo_header
pointer:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <string.h> char *data; struct foo_header header; void func(void) { memcpy(&header, data + offset, sizeof(header)); if (header.len < FOO) { int len; /* ... */ } } |
Noncompliant Code Example
For objects declared on the stack, the C Standard provides alignas
to declare an object to have a stricter alignment. It can be used to resolve the following noncompliant code example:
Code Block | ||||
---|---|---|---|---|
| ||||
#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 | ||||
---|---|---|---|---|
| ||||
#include <stdalign.h> /* For alignas() */ #include <assert.h> void func(void *data, size_t offset) { 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 */struct foo_header header; memcpy(&header, data + offset, sizeof(header)); /* ... */ } |
Risk Assessment
Accessing a pointer or an object that is no longer on the correct access boundary can not properly aligned can cause a program to crash or give wrong information, or it can cause slow pointer accesses (if the architecture allows misaligned accesses).
...
[Bryant 2003] | |
[ISO/IEC 9899:2011] | Subclause 6.3.2.3, "Pointers" |
[Walfridsson 2003] | Aliasing, Pointer Casts and GCC 3.3 |
...