c - 从内存缓冲区读取结构会引发编译器错误和段错误

标签 c pointers casting compiler-warnings

在下面的代码中,我试图在原始内存缓冲区中存储一个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);

我得到一个段错误

两个问题:

一个。 Thing* thing_ptr = (Thing*) buffer[0]; 有什么问题?为什么会引发错误?

B.段错误的原因是什么?

最佳答案

线

Thing* thing_ptr = (Thing*) buffer[0];

不正确。

变量 buffer 是一个 uint8_t *,所以 buffer[0] 是一个 uint8_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] 警告表示您正在从不同大小的整数类型转换为指针。这种类型的转换通常没有意义。

出现此类警告的原因之一是为了防止出现类似您遇到的问题。


您的版本导致段错误,因为您解释了 uint8_tbuffer[0](可能是 080,取决于字节序)作为指针。这可能是个人计算机上的无效指针,取消引用它会导致您的平台出现段错误。

关于c - 从内存缓冲区读取结构会引发编译器错误和段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57595041/

相关文章:

从c中的指针复制特定字符

c - 关于char指针的几个问题

java - long 1l,float 1f,double 1d,byte呢?

c - 是否可以在不复制的情况下删除大文件的两端?

c - 无法弄清楚为什么 printf 在标准输出上打印不同

c - 任何人都可以向我解释以下内容

mysql - SELECT * 但也使用 CAST()

delphi - 在 Delphi XE3 中,如何使用 TypeInfo 或 RTTI 将 TVirtualInterface 对象强制转换为其接口(interface)?

c - 为什么我的线程合并排序比基本的递归合并排序慢? [复制]

c - 在 C 中使用结构指针进行数组赋值