指针转换平台是否依赖?

时间:2017-11-08 12:12:50

标签: c pointers casting

以下示例:

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

此外,指针指向平台/编译器/体系结构的地址是否依赖于某个地方是否存在此行为的定义?

2 个答案:

答案 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指向该数组的第一个元素,然后访问内容。这样做会导致“严格的别名违规”。