这种类型的铸造或某种指针算术?

时间:2015-04-30 11:47:12

标签: c++ pointers casting

我遇到了一系列用C ++编写的代码:

long *lbuf = (long*)spiReadBuffer;

事实证明“spiReadBuffer”是一个包含12个元素的字节数组。但我有点困惑。我认为我熟悉定义指针,我可以看到“lbuf”是一个类型“长”指针。我也想过铸造,我们可以这样做:

y = (int) x;    

但是如果我在“int”之后放一个“*”就像我的第一个例子那样,那里有一个“long”之后? 如果这是一个非常微不足道的问题我很抱歉,但是当我经历了类型转换和指针主题时,我没有遇到过我的情况而且我并没有真正理解它。 如果您能指导我或向我介绍任何相关材料或资源,我将不胜感激。

3 个答案:

答案 0 :(得分:1)

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

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

此方法的问题在于它会触发未定义的行为(请参阅 strict aliasing )。因此,即使它在很多情况下都有效,但它也可以在没有通知的情况下破坏。

有两种方式(我知道)安全地输入双关语。第一个是符合标准的: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;

标准规定写入联盟成员然后从另一个成员读取是未定义的行为。这些编译器扩展选择将其定义为安全重新解释。

答案 1 :(得分:0)

C / C ++数组中的

由编译器以相同的方式处理:

char  spiReadBuffer[12];
char* pBuffer;

编译器会将spiReadBuffer和pBuffer都视为指针。

代码段

long *lbuf = (long*)spiReadBuffer;

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

您展示的第二个片段:y = (int) x;也是演员,但不是指针;

答案 2 :(得分:0)

请考虑以下代码段:

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

它将在小端架构上打印04030201或在小端架构上打印01020304

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