I recently learned that pointer casting could trigger unaligned memory access, such as in
void test_func(uint8_t *data) {
/*The rest of the code removed for clarity*/
uint32_t value = *((uint32_t *) data);
}
But how can I work around it, if I really need to cast pointers? In the example above, what if I have to access data
as an uint32_t
but still want to avoid unaligned memory access?
How to work around pointer casting... to avoid unaligned memory access?
Use memcpy(&value, data, sizeof value);
to transfer the data instead of *((uint32_t *) data)
. A good compiler will emit efficient code.
uint8_t data[4] = { 1,2,3,4};
uint32_t value;
memcpy(&value, data, sizeof value);
... or insure the uint8_t value[]
is aligned with a union
, alignas
via *alloc()
union {
uint8_t data[4];
uint32_t d32;
} x;
...
test_func(x.data) {
#include <stdalign.h>
alignas(uint32_t) uint8_t data[4] = { 1,2,3,4};
test_func(data);
uint8_t *data = malloc(sizeof *data * 4);
...
test_func(data);
free(data);
How to work around pointer casting in C to avoid unaligned memory access?
You can't (eg on x86-64 unaligned memory access are possible, but slow; it might also be the case on Arduino -s).
See also _Alignas
and _Alignof
operators of C11.
On many implementations, a pointer can be casted back and forth from intptr_t
and you could then play bitwise tricks.
In the example above, what if I have to access
data
as anuint32_t
but still want to avoid unaligned memory access?
You need to ensure that the caller of test_func
is passing a well aligned pointer.
You could be helped by tools like Frama-C , the Clang static analyzer , or perhaps, at end of spring 2021, Bismon
You might #include <assert.h>
and add, as the first statement of your test_func
: assert((intptr_t)data % sizeof(uint32_t) == 0);
; see eg assert(3) .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.