以下示例:
void foo(void)
{
uint8* ptr_data8;
uint32* ptr_data32;
uint32 data32 = 255;
ptr_data32 = &data32;
ptr_data8 = (uint8*)ptr_data32;
}
因此,根据Endianess,内存可能会有所不同:
小端:
Address: [ 0| 1| 2| 3]
-------------------
Value: [255| 0| 0| 0]
大端:
Address: [ 0| 1| 2| 3]
-------------------
Value: [ 0| 0| 0| 255]
所以问题是,指针针对每个架构指向哪个地址?
指针指向整个数据元素的最低地址吗?
[Little Endian]
ptr_data8 --> 0
ptr_data32 --> 0
[Big Endian]
ptr_data8 --> 0
ptr_data32 --> 0
或者它们是否指向数据元素的最低值/字节?
[Little Endian]
ptr_data8 --> 0
ptr_data32 --> 0
[Big Endian]
ptr_data8 --> 0
ptr_data32 --> 3
此外,指针指向平台/编译器/体系结构的地址是否依赖于某个地方是否存在此行为的定义?
答案 0 :(得分:4)
您的猜测无法证明或反驳,因为标准不要求指针指向某个数字位置。
该标准要求您的uint32_t*
指针可转换为void*
,其与char*
(以及扩展名为uint8_t*
)指针具有相同的表示形式。编译器必须能够像这样“往返”指针:
uint32_t *ptr32orig = ... // Assign some valid value
void *tmp1 = (void*)ptr32orig;
char *cptr = (char*)tmp1;
// cptr has the same representation as tmp1
void *tmp2 = (void*)cptr;
// At this point, tmp1 must be equal to tmp2
uint32_t *ptr32back = (uint32_t*)tmp2;
// At this point ptr32back must be equal to ptr32orig
这似乎意味着cptr
必须指向与ptr32orig
相同的位置,但这是不对的:允许编译器在转换{{1}时执行它想要的任何“魔法”转到ptr32orig
,然后撤消其对tmp1
转换回tmp2
的影响。
答案 1 :(得分:0)
我的猜测是否正确?如果没有,什么是对的?
是的,指针将指向第一个地址,无论结束。存储在该地址上的内容将根据字节顺序而有所不同。
指针指向平台/编译器/体系结构的地址是否依赖?
没有。
(C除了对指针在实践中的表示方式没有任何限制)
是否在某处定义了行为?
是。指针转换规则(C11 6.3.2.3)声明:
当指向对象的指针转换为指向字符类型的指针时, 结果指向对象的最低寻址字节。
此外,有效类型和严格别名(C11 6.5)的规则允许您通过指向字符类型(如{{}的指针来访问其他类型的数据。 1}}。
你不允许反过来做 - 如果你有一个uint8_t
数组,你不能用uint8_t
指向该数组的第一个元素,然后访问内容。这样做会导致“严格的别名违规”。