在一份 C++ 代码中,我找到了以下内容。有人可以帮我理解以下语句的含义吗?
char buffer[4096];
// some code
int size = *(int*)(buffer);
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答案。
int
的指针的错误内存对齐,它可能会在某些架构上崩溃。 - David Ranieri简而言之,这段代码很糟糕,不要再用了。
(buffer)
这个括号表示程序员对自己的编程能力缺乏信心。
由于buffer
是一个字符数组,仅使用标识符buffer
会给你一个指向第一个元素的指针:char
指针。
(int*)
这是一种类型转换,将char
指针转换为int
指针。
*
获取整数指针的内容,结果存储在整数size
中。
请注意,这段代码完全不安全。许多指针转换会调用定义不清的行为。可能存在对齐问题。可能存在指针别名问题(Google“strict aliasing rule”)。此特定代码还取决于字节顺序,这意味着它需要字符数组的内容具有给定的字节顺序。
总的来说,在做这样的事情时,使用有符号类型如int
或char
(也许是带符号的)没有任何意义。特别是,char
类型非常棘手,因为它具有实现定义的符号性并且应该避免使用。改用unsigned char
或者uint8_t
。
稍微好一点的代码看起来像这样:
#include <stdint.h>
uint8_t buffer[4096];
// some code
uint32_t size = *(uint32_t*)buffer;
memcpy
仍可能存在字节序问题,但至少不会有未定义行为。 - user694733unsigned char
将永远存在;而uint8_t
则可能不存在。 - Pete Beckerchar buffer[4096];
声明了一个大小为4096
的chars
数组。
第二个语句为:
int size = *(int*)(buffer);
1. 首先将已腐朽的字符指针传递给数组buffer
(也称为buffer
),该指针指向其第一个元素,在其声明时设置。int
或int*
的指针。int
类型)赋值给变量size
。buffer
” 是错误的,获取 buffer
的地址应该是 &buffer
。相反,buffer
会衰变为指向其第一个元素的指针。 - Some programmer dudebuffer[0]
的地址,将其强制转换为int*
,解引用该地址,并使用解引用后的值初始化size
。换句话说,它获取buffer
的前sizeof(int)
个字节,将这些字节视为一个int
,并将该int的值存储在size
中。buffer[0]
的地址。相反,数组会退化成指向其第一个元素的指针。 - Some programmer dude
(int*)buffer
的意思吗?如果不知道,可以了解一下类型转换。你知道一元解引用运算符*
是什么(例如当你有*some_pointer
时会发生什么)吗?如果不知道,也需要了解一下。然后把每个主题的知识结合起来,就像它们在你想知道的表达式中结合一样。 - Some programmer dudebuffer
的地址,将其转换为int *
,然后取消引用结果指针,这是未定义的行为。特别地,不能保证buffer
在接受int
边界上对齐。行为是未定义的。您不应尝试运行此代码。 - Tom Karzes