*(int*)(buffer) 的意思是什么?

6
在我阅读的 C++ 代码中,发现了以下内容。有谁能帮助我理解以下语句的作用?
在一份 C++ 代码中,我找到了以下内容。有人可以帮我理解以下语句的含义吗?
char buffer[4096];
// some code
int size = *(int*)(buffer);

8
你知道(int*)buffer的意思吗?如果不知道,可以了解一下类型转换。你知道一元解引用运算符*是什么(例如当你有*some_pointer时会发生什么)吗?如果不知道,也需要了解一下。然后把每个主题的知识结合起来,就像它们在你想知道的表达式中结合一样。 - Some programmer dude
2
这个语句在某些架构上可能会导致对齐异常。 - dbrank0
5
这个语句也会导致未定义行为。 - 2501
1
它正在获取buffer的地址,将其转换为int *,然后取消引用结果指针,这是未定义的行为。特别地,不能保证buffer在接受int边界上对齐。行为是未定义的。您不应尝试运行此代码。 - Tom Karzes
4个回答

14
char buffer[4096];//this is an array of 4096 characters
// some code

int size = *(int*)(buffer);

将已腐败的字符指针(即buffer)转换为整数指针。然后对其进行解引用以获取整数值。假设您的计算机中int的大小为4字节,则从中获取的整数值将由buffer数组的前4个字符值组成,或者通常由sizeof(int)个字符组成。

换句话说,前sizeof(int)个字符的内存表示形式将被视为代表单个整数值,因为现在它由整数指针指向,并且当该整数指针被解引用时,它将存储在size整数变量中。

话虽如此,正如评论部分已经反复说明的那样,此代码不安全。其中一件事是,某些CPU具有严格的对齐要求(请参见此答案),在这种情况下,不能保证buffer数组的第一个元素的地址符合整数对齐要求,导致在这些CPU上产生未定义操作。

更多关于此代码不安全并可能无法给您想要的结果的原因,请参见@Lundin答案。


@user694733,没错,由于指向int的指针的错误内存对齐,它可能会在某些架构上崩溃。 - David Ranieri
@user694733 谢谢您的反馈,我已经尝试提及一个我知道会在某些CPU上导致未定义操作的原因。Lundin的答案更详细地讨论了这段代码的问题,我觉得我会重复别人已经说过的话。 - Biruk Abebe

8

简而言之,这段代码很糟糕,不要再用了。


(buffer) 这个括号表示程序员对自己的编程能力缺乏信心。

由于buffer是一个字符数组,仅使用标识符buffer会给你一个指向第一个元素的指针:char指针。

(int*) 这是一种类型转换,将char指针转换为int指针。

* 获取整数指针的内容,结果存储在整数size中。

请注意,这段代码完全不安全。许多指针转换会调用定义不清的行为。可能存在对齐问题。可能存在指针别名问题(Google“strict aliasing rule”)。此特定代码还取决于字节顺序,这意味着它需要字符数组的内容具有给定的字节顺序。

总的来说,在做这样的事情时,使用有符号类型如intchar(也许是带符号的)没有任何意义。特别是,char类型非常棘手,因为它具有实现定义的符号性并且应该避免使用。改用unsigned char或者uint8_t

稍微好一点的代码看起来像这样:

#include <stdint.h>

uint8_t buffer[4096];
// some code
uint32_t size = *(uint32_t*)buffer;

5
我认为你的示例代码不应该使用指针解引用技巧。使用memcpy仍可能存在字节序问题,但至少不会有未定义行为。 - user694733
代码仍具有相同未定义行为,如何使其更少出错? - 2501
因为它没有提到的类型问题。展示如何修复这个问题是代码片段的目的。要修复未定义行为,您需要做一些更加激烈的事情。 - Lundin
1
提出的替代方案存在问题:它强加了一个原始代码中不存在的限制,即目标硬件必须提供8位本地类型和32位本地类型。这可能是一个有效的更改,但是对于那些对原始代码有不同要求的代码示例,应该指出这些差异。unsigned char将永远存在;而uint8_t则可能不存在。 - Pete Becker

3
我可以帮助您理解以下语句的含义吗?
第一条语句:
char buffer[4096];

声明了一个大小为4096chars数组。

第二个语句为:

int size = *(int*)(buffer);
1. 首先将已腐朽的字符指针传递给数组buffer(也称为buffer),该指针指向其第一个元素,在其声明时设置。

2. 然后将其转换为指向intint*的指针。

3. 最后,将此指针的内容(将是int类型)赋值给变量size

“first takes the address of array buffer” 是错误的,获取 buffer 的地址应该是 &buffer。相反,buffer 会衰变为指向其第一个元素的指针 - Some programmer dude
1
除非回答也解释了为什么这段代码是错误的,不然我不能点赞。 - user694733
@user694733 的确,如果只有一个答案清楚地解释了为什么这是UB。 - 2501

1
它获取buffer[0]的地址,将其强制转换为int*,解引用该地址,并使用解引用后的值初始化size。换句话说,它获取buffer的前sizeof(int)个字节,将这些字节视为一个int,并将该int的值存储在size中。

2
它并不直接获取buffer[0]的地址。相反,数组会退化成指向其第一个元素的指针。 - Some programmer dude
1
我不能点赞,除非答案还解释了为什么这段代码是错误的,不应该使用。 - user694733

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接