C 指针强制转换是否依赖于平台?

C 指针强制转换是否依赖于平台?,c,pointers,casting,C,Pointers,Casting,以下示例: void foo(void) { uint8* ptr_data8; uint32* ptr_data32; uint32 data32 = 255; ptr_data32 = &data32; ptr_data8 = (uint8*)ptr_data32; } 因此,根据端部的不同,内存可能会有所不同: 小恩迪亚: Address: [ 0| 1| 2| 3] -------

以下示例:

void foo(void)
{
    uint8* ptr_data8;        
    uint32* ptr_data32;
    uint32 data32 = 255;

    ptr_data32 = &data32;

    ptr_data8 = (uint8*)ptr_data32;
}
因此,根据端部的不同,内存可能会有所不同:

小恩迪亚:

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
还是它们指向数据元素的最低值/字节?

[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

此外,指针指向平台/编译器/体系结构的地址是否与平台/编译器/体系结构相关?是否有此行为的定义?

您的猜测无法证明或反驳,因为标准不要求指针指向某个数字位置

该标准要求您的
uint32*
指针可转换为
void*
,该指针与
char*
(扩展为
uint8*
)指针具有相同的表示形式。编译器必须能够“往返”指针,如下所示:

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
必须指向与
ptr320rig
相同的位置,但这是不对的:编译器可以在将
ptr320rig
转换为
tmp1
时执行它想要的任何“魔法”,然后撤消其将
tmp2
转换回
uint32.*
的效果

我的猜测正确吗?如果没有,什么是正确的

是的,指针将指向第一个地址,无论是否为endianess。存储在该地址上的内容将根据endianess的不同而有所不同


指针指向平台/编译器/体系结构的地址是否依赖

没有

(C对指针在实际中的表示方式没有任何限制除外)


这种行为是在什么地方定义的

对。指针转换规则(C116.3.2.3)规定:

当指向对象的指针转换为指向字符类型的指针时, 结果指向对象的最低寻址字节

此外,有效类型和严格别名规则(C116.5)允许您通过指向字符类型(如
uint8\t
)的指针访问其他类型的数据


但是,不允许使用其他方法-如果您有一个
uint8\u t
数组,则不允许使用
uint32\u t*
指向该数组的第一个元素,然后访问内容。这样做将是一种“严格别名冲突”。

如果您想要操纵位,请使用位运算符Related:。您确定严格别名要求指针相等吗?当您将
uint32\u t*
转换为
uint8\u t*
以允许逐字节访问正确进行时,编译器不能给您一个数字不同的指针吗?uint8\u t不需要是字符类型的typedef(6.2.5)@dasblinkenlight该要求实际上并非来自严格的别名,而是来自指针转换规则,C116.3.2.3:“当指向对象的指针转换为指向字符类型的指针时,结果指向对象的最低寻址字节。”让我把这段文字添加到答案中。答案很好,谢谢你参考C标准。是否也在某个地方定义了指针(无转换)指向对象的最低地址?@Stargateur此类实现不支持
uint8\u t
,因此具体情况无关紧要。此外,现实世界中仅有的
char
类型宽度超过8位的系统是各种功能失调的、大多是过时的DSP,其中大多数来自TI。任何设计C源代码与这些DSP兼容的人都是在浪费时间。任何用C语言而不是汇编语言为这些DSP编写程序的人都很可能会感到困惑。相反,请设计与现实世界计算机兼容的C程序。不过,C语言确实允许通过字符类型的左值表达式(如uint8)对
ptr32orig
指向的数据进行左值访问。如果您采用
*cptr
,则必须以某种实现定义的方式访问
ptr32orig
指向的数据。这确实意味着
cptr
必须指向与
ptr32orig
相同的位置。请注意,本示例中的所有类型转换都不需要。您的答案与您以前的答案不矛盾吗?“因此,允许将
int*
转换为
char*
,而且它是可移植的。指针将指向
int
内部表示的初始字节。”@MartinR否,强制转换后指针的值不必相同,但必须“指向”相同的字节。所以,只有当你去引用它时,@martiner,这并不矛盾。这里有一个例子:假设我有
uint32_t*ptr
,它等于
0xC003
,这个指针指向的
uint32_t
字节位于字节
0xc00..0xC003
中。标准要求,当我将
ptr
转换为
char*
时,我返回
0xC000
。它不要求强制转换为no-op,因此允许编译器执行一些“指针转换”。为了充分披露,我从未见过一个平台有如此疯狂的行为,但我不认为标准禁止这样做。