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,因此允许编译器执行一些“指针转换”。为了充分披露,我从未见过一个平台有如此疯狂的行为,但我不认为标准禁止这样做。