当 int 通常是 32 位或 64 位时,"int" 如何表示一个字节(8 位)?

How does an "int" represent a byte (8 bits) when an int is normally 32 or 64 bits?

我很好奇在 Dart 编程语言中一个字节是如何用 int 类型表示的。我很困惑,因为在 Dart 非常相似的 Java 中,int 是 32 位。

我问是因为领先的 flutter ble 库 Flutter Blue 在处理 ble 字节时似乎可以处理 List<int>

但是根据官方文档: https://flutter.dev/docs/development/platform-integration/platform-channels#codec 使用了 Uint8List - 这就是 byte[] 等价物的意义所在。

那些无符号的 8 位整数似乎只是从 Uint8List -> List<int> 转换为 32 位有符号整数?即十进制 2 然后从 00000010 转换为 00000000000000000000000000000010?

如果要写入字节流,这似乎会产生影响。需要将 int 转换为 Uint8

dart 中 int 的大小对于局部变量来说并不是完全可预测的,正如 Irn 提到的 。如果认为可能的话,int 的大小可能会减少作为优化。

如果您进行从 Uint8ListList<int> 的显式转换以创建新的 List 对象,则新对象将具有更大尺寸的 int 个元素超过 8 位。可能是 32 位,可能是 64 位,也可能更少。编译器将根据它所看到的进行选择。根据int class,默认是一个带符号的64位整数。

如果您尝试从 intUint8List,每个 int 将被截断为 8 位。

首先,让我们弄清楚一件事。 int 不是固有的 32 位或普遍的 64 位。这只是通用语言制定的约定,包括 Java。例如,在 C 中,int 的大小是一个实现细节,它取决于编译器、体系结构和内存地址的大小,因此它可以是 8、16、32 或 64 位(或在更深奥的平台上,完全不同的东西,比如 24 位)。因此,认为 Dart 没有 int 是 32 位整数类型是在做一些“错误”的事情的想法有点荒谬。

现在,Dart 中的 int 不是固定数据类型。与 C 一样,它取决于 运行 所在的平台。

  • 移动设备:int 是一个 64 位整数
  • Web: int 映射到 JavaScript Number 这是一个 64 位浮点数(即 double
  • 其他:int可以定义为实现细节

就是这样。 Dart 没有任何其他整数类型的概念。 (即没有像 byte、short、char、long、long long 等基本类型。)

您在 Uint8List 中看到的是对 64 位整数列表的抽象,使其看起来像字节列表。我不确定它在内部是如何表示的(每个“字节”都是它自己的 int,使用 bit-flags 在单个 int 中存储 8 个字节的信息,或者它是一个本机实现完全在做其他事情),但归根结底,这并不重要。

Uint8List 派生自 List<int>;在预期 List<int> 的地方传递 Uint8List 不会更改数据的表示形式。

当您从 Uint8List(例如 operator []阅读 单个 int 时,您将获得一份八位字节扩展为 int 是什么。

当您 一个 int 写入 Uint8List 时(例如使用 operator []=),存储的值将被截断以仅包含低 8 位。

关于如何使用 int 来表示字节不应该有任何混淆,因为它都归结为位以及您如何存储和操作它们。

为了简单起见,让我们假设 int 比一个字节大——一个 int 是 32 位,一个 byte 是 8 位。因为,此时我们只处理位,您可以看到 int 可能包含 4 个字节,因为 32/8 是 4,即我们可以使用 int 来存储字节而不会丢失信息。

It seems as those the unsigned 8 bit integers are just then converted to a 32 bit signed int going from Uint8List -> List ? i.e. decimal 2 is is then converted from 00000010 to 00000000000000000000000000000010?

可以那样做,但我之前说过,你可以在一个 int 中存储多个字节。

考虑一下,如果您有字符串 Hello, World!,它最多为 13 个字节,并且您想将这些字节存储在 int 的列表中,假设每个 int 是 32位;我们只需要用4个int来表示这个字符串,因为13 * 8是104位,4个32位的int可以容纳128位的信息。

It seems this has ramifications if one would like to write a byte stream. Would need to cast the int's to Uint8's.

不一定。

由字节 'H', 'e', 'l', 'l', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' 组成的字节流可以写入称为 Bit Array 的数据结构。上述流的位数组如下所示:

[01001000011001010110110001101100011011110010110000100000010101110110111101110010011011000110010000100001]

或 32 位整数列表:

[1214606444,1865162839,1869769828,33]

如果我们想将这个整数列表转换回字节,我们只需要读取 8 位块中的数据以检索原始字节。我将用这个简单编写的 dart 程序来演示它:

String readInts(List<int> bitArray) {
  final buffer = StringBuffer();
  for (var chunk in bitArray) {
    for (var offset = 24; offset >= 0; offset -= 8) {
      if (chunk < 1 << offset) {
        continue;
      }
      buffer.writeCharCode((chunk >> offset) & 0xff);
    }
  }
  return buffer.toString();
}

void main() {
  print(readInts([1214606444,1865162839,1869769828,33]));
}

可以按照相同的过程将字节转换为整数 - 您只需将每 4 个字节组合起来形成一个 32 位整数。

输出

Hello, World!

当然,您不需要自己编写这样的代码,因为 dart 已经在 Uint8List class

Dart int 类型是一个 64 位二进制补码数——除了为 web 编译时,它是一个没有小数部分的 64 位浮点数(JavaScript 数字它有一个整数值)。

如何在内部表示这些值取决于优化,如果运行时系统确定该值适合,则可以将它们表示为更小的值。那是一个优化,你将无法区分。

“字节”值是 0..255 范围内的整数。您显然可以将字节值存储在 int.

存储多个字节的最有效方法是 Uint8List,它实现了 List<int>。它将每个元素存储为一个八位字节。 当您从 Unit8List 中读取一个值时,其字节值由 int 表示。当您在 Uint8List 中存储 int 时,仅存储低 8 位。 因此它确实扩展读取和截断写入以在八位字节和 64 位值之间移动值。