我遇到了一系列用C ++编写的代码:
long *lbuf = (long*)spiReadBuffer;
事实证明“spiReadBuffer”是一个包含12个元素的字节数组。但我有点困惑。我认为我熟悉定义指针,我可以看到“lbuf”是一个类型“长”指针。我也想过铸造,我们可以这样做:
y = (int) x;
但是如果我在“int”之后放一个“*”就像我的第一个例子那样,那里有一个“long”之后? 如果这是一个非常微不足道的问题我很抱歉,但是当我经历了类型转换和指针主题时,我没有遇到过我的情况而且我并没有真正理解它。 如果您能指导我或向我介绍任何相关材料或资源,我将不胜感激。
答案 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)
由编译器以相同的方式处理:
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
很长。