这是类型转换还是某种指针算法

Is this type casting or some kind of pointer arithmetics?

本文关键字:指针 算法 类型转换      更新时间:2023-10-16

我看到了一行用C++编写的代码:

long *lbuf = (long*)spiReadBuffer;

事实证明,"spiReadBuffer"是一个包含12个元素的字节数组。但我有点困惑。我想我熟悉定义指针,我可以看到"lbuf"是一个类型为"长"的指针。我还认为,对于选角,我们可以做这样的事情:

y = (int) x;    

但是,如果我在"int"后面加一个"*",就像我的第一个例子一样,在"long"后面有一个呢?如果这真的是一个微不足道的问题,我很抱歉,但当我讨论打字和指点的话题时,我没有遇到我的情况,我也没有真正理解它。如果你能指导我或向我介绍任何相关的材料或资源,我将不胜感激。

这被称为类型punning。它欺骗编译器读取对象占用的内存,就好像它是另一种类型一样。

在您的情况下,数组spiReadBuffer衰减为指向其第一个元素的指针,然后该指针被强制转换并存储。当您取消引用此指针时,您将访问数组的开头,就好像它是long一样。

这种方法的问题在于它会触发未定义的行为(请参见严格别名)。因此,尽管它在很多情况下都有效,但它也可能在没有通知的情况下崩溃。

(据我所知)有两种方法可以安全地键入双关语。第一个是符合标准的:std::memcpy

char spiReadBuffer[12];
long rbAsLong;
std::memcpy(&rbAsLong, &spiReadBuffer, sizeof rbAsLong);
// rbAsLong contains the first four bytes of spiReadBuffer, reinterpreted as a long.

第二个涉及一个通常由编译器提供的扩展(但您应该检查一下),它扩展了并集的行为。

union {
char buf[12];
long asLong;
} spiReadBuffer;

该标准规定,给工会成员写信,然后从另一个成员那里阅读是未定义的行为。这些编译器扩展选择将其定义为安全的重新解释。

在C/C++中,编译器以相同的方式处理数组:

char  spiReadBuffer[12];
char* pBuffer;

编译器将把spiReadBuffer和pBuffer都当作指针。

代码片段

long *lbuf = (long*)spiReadBuffer;

是类型转换的一个示例,仅适用于指针类型。字符*转换为长*;您可以说这是一种指针算术,因为现在,您可以使用long*(而不是一次一个字节)从spiReadBuffer读取sizeof(long)字节。

您展示的第二个片段:y = (int) x;也是一个强制转换,但不适用于指针;

考虑一下这个片段:

char spiReadBuffer[] = {1,2,3,4,5,6,7,8};
long *lbuf = (long*)spiReadBuffer;
printf ("%08xn", lbuf[0]);

它将在小端架构上打印04030201,或在小端体系结构上打印01020304

long *lbuf = (long*)spiReadBuffer语句lBuf指向spiReadBuffer的开头之后,lbuf[0](或*lBuf)允许您将spiReadBuffer的前4个字节读取为长。