如何解决 C 中的指针转换以避免未对齐的内存访问?
How to work around pointer casting in C to avoid unaligned memory access?
我最近了解到指针转换可能会触发未对齐的内存访问,例如在
void test_func(uint8_t *data) {
/*The rest of the code removed for clarity*/
uint32_t value = *((uint32_t *) data);
}
但是如果我真的需要投指针,我该如何解决呢?在上面的示例中,如果我必须将 data
作为 uint32_t
访问,但仍想避免未对齐的内存访问怎么办?
How to work around pointer casting in C to avoid unaligned memory access?
你不能(例如,在 x86-64 上,未对齐的内存访问是可能的,但速度很慢;在 Arduino-s 上也可能是这种情况)。
另请参阅 _Alignas
and _Alignof
C11 的运算符。
在许多实现中,可以从 intptr_t
来回转换指针,然后您可以玩按位技巧。
In the example above, what if I have to access data
as an uint32_t
but still want to avoid unaligned memory access?
您需要确保 test_func
的 调用者 正在传递对齐良好的指针。
Frama-C, the Clang static analyzer, or perhaps, at end of spring 2021, Bismon
等工具可为您提供帮助
您可以 #include <assert.h>
并添加,作为您 test_func
的第一条语句: assert((intptr_t)data % sizeof(uint32_t) == 0);
;参见例如assert(3).
How to work around pointer casting ... to avoid unaligned memory access?
使用 memcpy(&value, data, sizeof value);
代替 *((uint32_t *) data)
传输数据。一个好的编译器会产生高效的代码。
uint8_t data[4] = { 1,2,3,4};
uint32_t value;
memcpy(&value, data, sizeof value);
... 或确保 uint8_t value[]
通过 *alloc()
与 union
、alignas
对齐
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);
我最近了解到指针转换可能会触发未对齐的内存访问,例如在
void test_func(uint8_t *data) {
/*The rest of the code removed for clarity*/
uint32_t value = *((uint32_t *) data);
}
但是如果我真的需要投指针,我该如何解决呢?在上面的示例中,如果我必须将 data
作为 uint32_t
访问,但仍想避免未对齐的内存访问怎么办?
How to work around pointer casting in C to avoid unaligned memory access?
你不能(例如,在 x86-64 上,未对齐的内存访问是可能的,但速度很慢;在 Arduino-s 上也可能是这种情况)。
另请参阅 _Alignas
and _Alignof
C11 的运算符。
在许多实现中,可以从 intptr_t
来回转换指针,然后您可以玩按位技巧。
In the example above, what if I have to access
data
as anuint32_t
but still want to avoid unaligned memory access?
您需要确保 test_func
的 调用者 正在传递对齐良好的指针。
Frama-C, the Clang static analyzer, or perhaps, at end of spring 2021, Bismon
等工具可为您提供帮助您可以 #include <assert.h>
并添加,作为您 test_func
的第一条语句: assert((intptr_t)data % sizeof(uint32_t) == 0);
;参见例如assert(3).
How to work around pointer casting ... to avoid unaligned memory access?
使用 memcpy(&value, data, sizeof value);
代替 *((uint32_t *) data)
传输数据。一个好的编译器会产生高效的代码。
uint8_t data[4] = { 1,2,3,4};
uint32_t value;
memcpy(&value, data, sizeof value);
... 或确保 uint8_t value[]
通过 *alloc()
union
、alignas
对齐
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);