【问题标题】:Reading from void pointer -- reinterpret_cast okay?从 void 指针读取——reinterpret_cast 好吗?
【发布时间】:2014-10-14 14:54:27
【问题描述】:

我已经调试我的代码有一段时间了,我需要检查一下 reinterpret_cast 不是问题所在。使用 C/C++ 已经有一段时间了,我可能会忘记基础知识。

在我的函数中,我得到了一些通用数据void *data 从传入的其他参数中,我知道数据的大小以及某些类型的偏移位置。例如,data 的大小为 12 个字节:前 4 个字节是 int,接下来 4 个字节是 chars,最后 4 个字节是 int。

问题: 我将如何从数据中获取数据的每个和平(int、char、char、char、char、int)?到目前为止,我一直在使用 reinterpret_cast 并且它有效!但是,由于我使用的是 reinterpret_cast,我的值(memFirst4、memA、memB 等)不是我所期望的,是否会出现这种情况?

void *data = malloc((sizeof(int)*3)); // 12 bytes .. my compiler has ints as 4 bytes
int first4 = 8075;
char a = 'a';
char b = 'b';
char c = 'c';
char d = 'd';
int last4 = 981;
memcpy(data,&first4,sizeof(int)); // copy first4 into memory
memcpy(data+sizeof(int)+sizeof(char)*1,&a,sizeof(char)); // copy char a into memory
memcpy(data+sizeof(int)+sizeof(char)*2,&b,sizeof(char)); // copy char b into memory
memcpy(data+sizeof(int)+sizeof(char)*3,&c,sizeof(char)); // copy char c into memory
memcpy(data+sizeof(int)+sizeof(char)*4,&d,sizeof(char)); // copy char d into memory
memcpy(data+sizeof(int)+sizeof(char)*4+sizeof(int),&last4,sizeof(int)); // copy last4 into memory

int memFirst4 = *reinterpret_cast<int *>(data);
char memA = *reinterpret_cast<char *>(data+sizeof(int)+sizeof(char)*1);
char memB = *reinterpret_cast<char *>(data+sizeof(int)+sizeof(char)*2);
char memC = *reinterpret_cast<char *>(data+sizeof(int)+sizeof(char)*3);
char memD = *reinterpret_cast<char *>(data+sizeof(int)+sizeof(char)*4);
int memLast4 = *reinterpret_cast<int *>(data+sizeof(int)+sizeof(char)*4+sizeof(int));
free(data);

【问题讨论】:

  • reinterpret_cast 是正确的工具。它只需要一个指针,并允许您取消引用它,就好像它是您传递的类型一样。您预计会在哪里出现问题(除了 int 可能并不总是 4 个字节)?
  • 啊,你最后一次投错了,额外的sizeof(int)太多了。
  • 除第一个偏移量之外的所有偏移量都是错误的。
  • @Adam:所有的字符都是用1关闭写入和读取,最后一个int在分配的缓冲区之后写入。
  • @Adam 拿一些纸,画 12 个盒子,然后为每个调用检查指针指向的盒子。它必须始终指向您要写入或读取的内存的开始

标签: c++


【解决方案1】:

您的解决方案会起作用,但风险很大(容易出错,少复制一个字节或多复制一个字节)。因此,我会推荐一个工会:

#pragma pack(1)
union myData
{ 
  char data[12];
  struct fields 
    { 
      uint8_t i[4];
      char c[4];
      uint8_t i2[4];
    } u_fields;
}
#pragma pack(pop) 

Union 允许您以不同类型读取相同的内存块(在本例中使用 char[12] 数据和字段结构)。

Have a look here for more info

【讨论】:

  • 这行得通吗?通常,structs 被填充,这不是在 unions 内部完成的吗?此外,他想要int,而不是uint8_t[4]
【解决方案2】:

您不应该使用 reinterpret_cast。不允许使用 reinterpret_cast 从 void* 转换一些指针。

当你想从 void* 转换成别的东西时,你可以使用 static_cast。但请记住,在两者之间使用 void* 从一种类型转换为另一种(不相同的)类型将产生一个未指定的指针值。

【讨论】:

  • 我认为 C++11 不再是这样。此外,我使用的任何编译器都没有针对 C++03 进行过检查,p == reinterpret_cast&lt;type*&gt;(reinterpret_cast&lt;void*&gt;(p)) 始终受到标准的保证。
猜你喜欢
  • 2014-02-06
  • 1970-01-01
  • 2014-05-30
  • 2020-04-01
  • 1970-01-01
  • 2021-04-08
  • 2021-07-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多