是否可以在 C++ 中创建一个占用少于一个字节内存的类型?

Is it possible to create a type in c++ that takes less than one byte of memory?

对于我的计算,我只需要使用 7 位space,所以我使用的是 char 类型。但是我想知道是否可以声明我自己的使用少于一个字节内存的类型?

byte是最小可寻址单元,在C++中最小大小为1。内存以字节为单位分配。即使是空 class 也至少有不小于 1 个字节的大小。

即使您尝试创建大小为 1 的位集,它也会消耗一个字节。所以在C++中不可能创建小于一个字节的类型

#include <iostream>       // std::cout
#include <string>         // std::string
#include <bitset>         // std::bitset

int main ()
{
  std::bitset<1> foo;
  std::bitset<1> bar (1);
  std::bitset<1> baz (std::string("1"));

  std::cout << "foo: " << sizeof(foo) << '\n';
  std::cout << "bar: " << sizeof bar << '\n';
  std::cout << "baz: " << sizeof baz << '\n';

  return 0;
}

不是真的。在结构内部,您可以使用 bit fields。因此,如果您知道您将需要一定数量的条目,这将是一种节省一些位的方法(但请注意,该结构将始终至少填充到下一个字节总数)。另请注意,由于 "normal" CPUs 无法寻址小于 octet/byte 的数量,因此由于编译器的额外指令,对这些位字段值的访问可能会更慢必须为 get/store 生成一个值 "in the middle"。所以为了节省一点点,你必须花费一些CPU时间。

C++11 standard 在第 1.7 章中说 C++ 内存模型(强调我的):

The fundamental storage unit in the C++ memory model is the byte. A byte is at least large enough to contain any member of the basic execution character set (2.3) and the eight-bit code units of the Unicode UTF-8 encoding form and is composed of a contiguous sequence of bits, the number of which is implementation- defined.

换句话说:C++中最小的可寻址单元至少是8位宽。

旁注:如果您想知道:there are machines like DSPs that can only address units larger than 8 bits at a time;对于这样的机器,编译器可以将 "byte" 定义为例如 16 位宽。

对于小于一个字节的对象,sizeof 会给出什么? 0到1之间的整数值?

sizeof 字节 给出其操作数的大小,并且 0 显然不是可能的结果,因此 1最小的可能大小,因为 sizeof 的 return 类型是整数类型。因此,任何对象的内存表示都不能少于一个字节。

假设处理器不是一些与常规硬件完全不同的特殊硬件,使用 7 位而不是 8 位不会有任何好处,因为 8 位字节是最小可寻址单元(除了一些使用超过 8 位到一个字节的奇异机器,在我使用计算机 30 多年的时间里,除了我的一个朋友在暑期实习期间工作的霍尼韦尔大型机外,我没有使用过一台主机,我被邀请参观一天 - 我不知道它是什么型号,所以它可能是一台 18 位或 36 位机器 - 那是大约 1985 年左右)。

因此,假设您可以创建一个 7 字节的大数组 "lumps",编译器将不得不生成额外的代码来从数组中提取每个 7 字节的元素,因此不用执行一条指令来获取一个 8 位字节,所有访问将至少进行两次操作,有些访问将跨越两个机器字,需要再进行两次操作才能从两个机器字中提取 7 位的相关组合。这是可能的,但它很可能会浪费超过 space 中使用 8 位字所浪费的 1/8。换句话说,即使您可以做到,性能也会下降而不是提高。

如果有一台 512 位字机,这可能是合理的,因为这样您就可以将 73 个 7 位字放入一个 512 位字中。但是 512 位字机并不常见,甚至 x86-64 处理器上设置的 AVX512 指令也不是真正的 512 字节字,您不能(轻松地)访问每第 7 位作为位域,您必须洗牌一次 8、16、32、64 块等。