在下面的代码中,我试图将struct
存储在原始内存缓冲区中。
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
typedef struct {
int a;
} Thing;
int main(void) {
uint8_t* buffer = malloc(sizeof(Thing) * 200);
Thing thing;
thing.a = 80;
memcpy(buffer, &thing, sizeof(Thing));
Thing* thing_ptr = (Thing*) buffer[0];
return 0;
}
但是,我收到以下编译器警告:
warning: cast to 'Thing *' from smaller integer type
'uint8_t' (aka 'unsigned char') [-Wint-to-pointer-cast]
Thing* thing_ptr = (Thing*) buffer[0]
另外,当我试图在最后解引用
thing_ptr
时:printf("%d\n", thing_ptr->a);
我得到一个
segmentation fault
。两个问题:
A.
Thing* thing_ptr = (Thing*) buffer[0];
怎么了?为什么会引发错误?B.segfault的原因是什么?
最佳答案
线路
Thing* thing_ptr = (Thing*) buffer[0];
不正确。
变量
buffer
是auint8_t *
,因此buffer[0]
是auint8_t
。在这种情况下,buffer[0]
等同于*buffer
。有两种选择:
您可以取
buffer[0]
的地址:Thing* thing_ptr = (Thing*) &buffer[0];
在这种情况下,这没有多大意义,尽管它可以澄清意图在其他一些情况下。
在我看来,更好的选择是放弃
[0]
:Thing* thing_ptr = (Thing*) buffer;
这清楚地表明您正在将
buffer
中的值从类型uint8_t *
转换为Thing *
。[-Wint-to-pointer-cast]
警告表示您正在从不同大小的整数类型转换到指针。这种类型的演员通常没有意义。这种警告存在的原因之一是防止像你所经历的那样的问题。
您的版本会导致segfault,因为您将
uint8_t
值buffer[0]
(可能是0
或80
,取决于endianness)解释为指针。这可能是个人计算机上的无效指针,取消对它的引用会导致平台上出现segfault。关于c - 从内存缓冲区读取结构会引发编译器错误和segfault,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57595041/