为什么在使用指针访问未对齐的 uint16 数组时抛出 "alignment exception" 而在使用下标访问数组时不抛出?
Why is an "alignment exception" thrown when accessing an unaligned uint16 array with a pointer but not when accessing the array using subscripts?
我将使用以下代码来解释我的问题:
typedef struct __attribute__((packed))
{
uint8_t var;
uint16_t array[3];
}struct_t;
uint8_t frame[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD};
volatile struct_t *ptr = NULL;
volatile uint16_t *u16ptr = NULL;
volatile uint16_t a;
volatile uint16_t b;
//******************************************************************************************
int main(int argc, char** argv)
{
ptr = (struct_t*)frame;
u16ptr = ptr->array;
a = ptr->array[0]; // <---- NO Memory Access Exception here
b = *u16ptr; // <---- Memory Access Exception here!
}
在那段代码中,我强制array
内存未对齐以产生内存访问异常。
所以我的问题是,为什么在通过指针访问未对齐的 uint16 数组时抛出 "alignment exception" 而在使用数组下标访问数组时不抛出?
到目前为止我发现的 None 资源解释了为什么 a = ptr->array[0];
和 b = *u16ptr;
行都访问完全相同的未对齐内存。
有人可以解释一下或指出正确的方向吗?
尝试从未对齐的地址读取 16 位值会陷入某些架构师的陷阱。尽管标准将 x[y]
的行为定义为等同于 *((x)+(y))
,这将导致数组被分解为指针,然后从该地址获取值(如果地址未对齐则捕获) , clang 和 gcc 都将 structOrUnion.memberArray[index]
视为标识 structOrUnion
成员的一部分的左值,而不是将 structOrUnion.memberArray
分解为指针的表达式,忘记指针来自何处,然后对其进行索引。
如果 []
运算符直接用于 "packed" 结构成员的未对齐数组,或联合的任何数组类型成员,clang 和 gcc 将执行它们的操作需要做的访问有问题的存储。但是,如果这样的数组被分解为指针,则 clang 和 gcc 都不会可靠地允许使用它来访问其类型的对象。
我将使用以下代码来解释我的问题:
typedef struct __attribute__((packed))
{
uint8_t var;
uint16_t array[3];
}struct_t;
uint8_t frame[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD};
volatile struct_t *ptr = NULL;
volatile uint16_t *u16ptr = NULL;
volatile uint16_t a;
volatile uint16_t b;
//******************************************************************************************
int main(int argc, char** argv)
{
ptr = (struct_t*)frame;
u16ptr = ptr->array;
a = ptr->array[0]; // <---- NO Memory Access Exception here
b = *u16ptr; // <---- Memory Access Exception here!
}
在那段代码中,我强制array
内存未对齐以产生内存访问异常。
所以我的问题是,为什么在通过指针访问未对齐的 uint16 数组时抛出 "alignment exception" 而在使用数组下标访问数组时不抛出?
到目前为止我发现的None 资源解释了为什么 a = ptr->array[0];
和 b = *u16ptr;
行都访问完全相同的未对齐内存。
有人可以解释一下或指出正确的方向吗?
尝试从未对齐的地址读取 16 位值会陷入某些架构师的陷阱。尽管标准将 x[y]
的行为定义为等同于 *((x)+(y))
,这将导致数组被分解为指针,然后从该地址获取值(如果地址未对齐则捕获) , clang 和 gcc 都将 structOrUnion.memberArray[index]
视为标识 structOrUnion
成员的一部分的左值,而不是将 structOrUnion.memberArray
分解为指针的表达式,忘记指针来自何处,然后对其进行索引。
如果 []
运算符直接用于 "packed" 结构成员的未对齐数组,或联合的任何数组类型成员,clang 和 gcc 将执行它们的操作需要做的访问有问题的存储。但是,如果这样的数组被分解为指针,则 clang 和 gcc 都不会可靠地允许使用它来访问其类型的对象。