对C++中的字节字段使用char*或void*或其他什么

Use char* or void* or something else for byte fields in C++?

本文关键字:char void 什么 其他 C++ 字节 字段      更新时间:2023-10-16

我有一些字节字段,其中包含不同数字类型的字段。指向这些字段的指针随后被传递并作为成员存储在其他类中。

指针类型应该使用char*还是void*

目前,我只看到char*的一个优点:您不能取消引用void*。从字段中读取值时,这不是问题,因为无论如何我都必须转换为相应的指针类型。如果我想逐字节地对字段进行纯拷贝,我首先需要将void*强制转换为char*,因此更容易将其直接存储为char*

或者有什么理由不使用char*

一般来说,我希望尽可能保持低级别,因为我必须将字段传递给其他低级别接口。

将char*用于内存块"很容易使用"(e.b.逐字节操作),但它对阅读和理解代码非常不利(然而,您仍然可以在各种API中看到它)。

如果您的数据只是一块内存,那么最好使用void*。

只有当数据是特定类型的数组(char、int、uint8_t、somestruct…)时,才使用该类型的指针。

如果您需要将结构视为"字节数据"(例如计算哈希),则可以在内部将其视为"char*"(或uint8_t*或uint_32_t*或您需要的任何内容)。然而,如果您不需要特定的内存布局,那么公共API应该仍然是无效的。

要点是:如果你有一个使用void*的API,你可以为它提供任何类型的指针(这是一个散列函数的点)。但是,如果您使用char*,那么您总是需要一个reinterpret_cast。

使用char可能会引发一些问题——这完全取决于您希望如何处理存储在此类指针后面的值。

问题是,byte通常被解释为无符号值。例如:UTF-8编码。它生成字节序列,根据编码的代码点,这些字节可以具有不同的值。如果我们使用有符号类型,我们必须将值强制转换为无符号类型,才能正确检查它们的值(大于U+007F的代码点总是转换为字节序列,其中所有字节的符号位都设置为1)。

但是char是否被签名取决于实现。事实上,C++标准定义了三种不同的类型:

  • char
  • 有符号字符
  • 无符号字符

如果包含#include <limits.h>,则可以查看CHAR_MIN:

  • 如果定义为0,则char无符号
  • 如果定义为某个负值(通常为-128),则char是有符号的

那么,这一切意味着什么?

您应该以一种方式存储字节,这将允许您在不进行额外检查的情况下读取/写入它们的值。您可能希望您的字节是无符号值,所以定义新类型(就像许多高级语言所做的那样):

typedef unsigned char Byte;

然后,将您的指针定义为:

Byte* data_pointer;

然后,如果您的函数期望"void*"或"Byte*",则无需执行任何操作。但是,如果它们期望指向特定数字类型(intfloat等)的指针,则需要reinterpret_cast

非常简单且资源不足的是类型化指针的简单联合,据我所知,实际类型是由上下文决定的,这非常适合。

在运行时动态的另一端增强::任何