究竟啥是“位填充”或“填充位”?

Posted

技术标签:

【中文标题】究竟啥是“位填充”或“填充位”?【英文标题】:What is "bit padding" or "padding bits" exactly?究竟什么是“位填充”或“填充位”? 【发布时间】:2020-02-14 12:51:23 【问题描述】:

我不想用这个来骚扰你,但我在互联网上的任何地方都找不到关于“位填充”真正是什么的详细解释,也没有任何关于位填充相关线程的答案在 *** 上。

我还搜索了 ISO 9899-1990,其中提到了“位填充”,但由于我需要它而没有解释。

我在网上找到的唯一关于此的内容是here,其中只对一句话给出了一个荒谬的简短解释,说:

位填充:

位填充是向传输或存储单元添加一个或多个额外位,以使其符合标准大小。

一些来源将位填充识别为bit stuffing 的一种类型。

这至少是某种信息,但对我来说还不够解释。我不太明白这到底是什么意思。它也提到了这个词 "bit stuffing".


当我在 StockOverflow 上查看“padding”的相关标签时,填充被描述为:

在内存结构中插入额外空间以实现地址对齐 - 或 - 框架和 html 元素内容之间的额外空间 - 或 - 使用格式化打印命令(如 C 中的 printf)打印值时的额外空格或零*-函数族。

背景:

我经常发现与数据类型相关的术语“位填充”,但不明白它是什么,也不明白它对这些数据的作用。

非常感谢您提供任何基于主题的回答。

【问题讨论】:

是“在内存结构中插入额外空间以实现地址对齐”你能问得更具体点吗?我不知道在你已经发布的内容中添加什么 I often find the term "bit padding" in relation of data types - 你有例子吗? 该链接对搜索“位填充”的命中率为零。无论如何,众所周知,该网站充斥着错误信息 好吧,我发现他们提到填充位的地方,不过你最好选择不同的来源。 (我真的很犹豫告诉别人在哪里读什么,但这是一个例外) 为什么投反对票? OP 清楚地展示了研究工作,对我来说,这似乎是一个有用且清晰的问题,需要投票。否决票是针对没有研究成果的问题,因此不清楚且无用。我错过了什么吗? 【参考方案1】:

我经常发现与数据类型有关的术语“位填充”,但不明白它是什么,也不明白它对这些数据的作用。

它的要点是它们是“浪费”的空间。我说“浪费”是因为虽然填充位会使对象更大,但它可以使处理对象更容易(这意味着更快),并且小的空间浪费可以产生巨大的性能提升。在某些情况下,这是必不可少的,因为 CPU 无法处理这种大小的对象。

假设你有一个类似的结构(所有数字只是一个例子,不同的平台可以有不同的值):

struct foo

    short a; // 16 bits
    char  b; // 8 bits 
;

您正在使用的机器在一次读取操作中读取 32 位数据。读取单个 foo 不是问题,因为整个对象都适合该 32 位块。真正成为问题的是当你有一个数组时。关于数组要记住的重要一点是它们是连续的,元素之间没有空格。它只是一个对象紧接着另一个对象。所以,如果你有一个像

这样的数组
foo array[10];

这样,第一个 foo 对象位于 32 位存储桶中。数组的下一个元素将在第一个 32 位存储桶和第二个 32 位存储桶中。这意味着成员 a 位于两个单独的存储桶中。一些处理器可以做到这一点(需要付出代价),如果你尝试这样做,其他处理器就会崩溃。为了解决这两个问题,编译器将在foo 的末尾添加填充位以填充它的大小。这意味着 foo 实际上变成了

struct foo

    short a; // 16 bits
    char  b; // 8 bits 
    char  _; // 8 bits of padding
;

现在处理器可以很容易地自己处理foo 对象或在数组中。它不需要做任何额外的工作,每个对象只添加了 8 位。您需要很多对象才能开始在现代机器上发挥作用。

由于未对齐的访问,有时您需要在类型的成员之间进行填充。假设你有

struct bar

    char c; // 8 bits
    int  d; // 32 bits
;

现在bar 是 40 位宽,d 更多时候不会再次存储在两个不同的桶中。为了解决这个问题,编译器在cd 之间添加了填充位

struct bar

    char    c; // 8 bits
    char _[3]; // 24 bits
    int     d; // 32 bits
;

现在d 保证进入单个 32 位存储桶。

【讨论】:

'@Nathan Oliver' 非常感谢这个例子。我不知道机器正在读取每个块的数据。因此,从逻辑上讲,向该结构添加位以使其元素对机器具有更好的可读性,这当然也意味着执行时的速度优势,好的。当我只有一个不适合的变量时,如何完成位填充那块 32 位,fe short int a = 145; ? 如果该成员是类的一部分,则可以添加传递。如果对象只是一个局部变量,编译器可能会决定将下一个变量放在它自己的存储桶中。其中很多是实现定义的,因为 C++ 建模的抽象机器并不关心。【参考方案2】:

位填充可用于多种上下文。两个常见的例子是网络和加密。我相信加密上下文更相关。

填充用于加密,使解密具有共同部分的消息变得更加困难。如果已知多条消息具有相同的前缀(例如,“hello”),则更容易破解密钥。通过使用可变长度的位字段“填充”消息,更难破解密钥。

据说英国情报部门能够加快对 Enigma 信息的分析速度,因为德国人以相同的标题开始他们的信息。

如需更多技术性、准确的描述:https://en.wikipedia.org/wiki/Padding_(cryptography) 查找有关分组密码和位填充的部分

【讨论】:

在内存存储的情况下如何使用位填充? 我的答案中的示例从字面上回答了这个问题;)【参考方案3】:

假设您有一个 8 位数字,它是 uint8_t,其值设置为 4。这可能会存储为a = 0000 0100。现在,假设您希望将其转换为 16 位数字。会发生什么?您必须为此数字中的“新”位分配一些值。你会如何分配他们?您不能随机分配零或一,原始变量的值会发生变化。根据架构等,您必须用额外的位填充值。在我的情况下,这意味着在原始 MSB(最高有效位)前面添加了额外的八个额外零,使我们的编号为 a = 0000 0000 0000 0100

值仍然是 4,但现在您可以分配 [0, 2^16) 范围内的任何内容,而不是 [0, 2^8) 范围。

【讨论】:

【参考方案4】:

位填充: 位填充是向传输或存储单元添加一个或多个额外位,以使其符合标准大小。

由于您发布的定义已经正确,我将尝试举例说明:

假设您必须存储占用少于 32 位但您有 4 字节插槽的数据。通过访问每个插槽更容易访问该数据,因此您只需完成所有 32 位。完成“给定空间”所需但不属于数据一部分的额外位符合位填充。

我相信在多种情况下可能会有更好的例子。任何人都可以随意编辑和/或通过新的改进或示例来完善答案。

希望这会有所帮助!

【讨论】:

虽然我明白了,你很想帮助我,而且你的风格非常优雅,顺便说一句,我非常感谢;-),我还是不明白。你说Suppose you have to store data that occupies less than 32 bits but you have 4 byte slots这就是我的理解。但是在It is easier to access that data by accessing to each slot, so you just have to complete all the 32 bits.,我不太明白你的意思。 1. 为什么我需要访问int32_t var f.e. 的每个字节完全靠自己,我该怎么做? 2.为什么我必须通过字节访问来完成所有32位? 正要回答您的评论,但刚刚看到 Nathan 的回答,它通过示例深入解决了所有这些问题。有没有留下,或者是你一直在寻找的答案?

以上是关于究竟啥是“位填充”或“填充位”?的主要内容,如果未能解决你的问题,请参考以下文章

究竟啥是 AWS 中的“承担”角色?

究竟啥是 flex-basis 属性集?

汇编: MOVSX的填充方式是:用源操作数的符号位来填充目的操作数的高位数据位

究竟啥是“特级”?

究竟啥是绑定?

究竟啥是 JavaBean?