是否需要保留填充位?

Do padding bits need to be preserved?

MSP430X 架构是 16 位 MSP430 架构到 20 位地址的扩展 space。这是通过将处理器的寄存器扩展到 20 位,将最小可寻址单元保持在一个八位字节(CHAR_BIT 等于 8)来完成的。

在这个体系结构上,人们可以想到一种 C 编程语言的实现,它为 int 提供 20 位整数类型,使用 8 位 char,16 位 [=13] =] 和模拟的 32 位 long。由于 20 不是 CHAR_BIT 的倍数,因此在存储 int 类型的变量时需要一些填充位。例如,可以用四个字节存储一个 int,留下一个字节和另一个字节的四位作为填充。

在阅读了标准关于整数类型的填充位的内容后,我不确定它们应该如何表现。由于在这种情况下填充仅用于存储,因此它们的值既不能设置也不能观察,除非通过类型双关。即便如此,复制这个 20 位类型的对象也不会复制任何填充位。 ISO 9899:2011允许这种填充位吗?

一般来说,标准对 sizeof 类型有一些限制。基本约束是它必须是 char 的倍数,而 sizeof(char) 定义为 1

类型内的填充位,参考6.2.6.1, which leaves the representation mostly implementation defined. 6.2.6.2p5说明填充位的值未指定;不需要保留,但是padding bits有两个重要的约束:

  1. 有符号整数中的正值应表示相同无符号类型的相同值。这保证了相同类型的有符号和无符号变量在有符号变量范围内的正值之间的兼容性。
  2. 如果所有位都为零,则表示值0。所以所有填充位也必须为 0。然而,反之则不然(感谢 MattMcNabb)。

两个都包含 填充位,因为它们是内部表示的一部分。从更实际的角度来看,填充位应设置为零,除非存在奇偶校验等依赖于其他位的位(但必须满足第二个约束)。

这是一个粗略的解释。有关详细信息,请参阅其余引用部分。

在 MSP430X 上,20 位 int 几乎没有实际用处。它们主要是为了扩展寻址范围,而不是用于整数运算(尽管指令集显然支持它——我在之前的编辑中错了)。

指针有 sizeof 32 位(4 个 8 位字节),但只使用 20 位。一些嵌入式编译器可能支持特殊的 short/near/... 限定符,有效地提供两种不同的指针大小。然而,这实际上违反了标准。 (我在这里有点矛盾:优化还是可移植性)。

MSP430X 是使用 stdint.huintptr_t)和 stddef.h(例如 size_t)的专用类型的平台之一 必不可少,因为投射指针 to/from int 最终会失败。更重要的是,标准对 (u)intptr_t (临时存储,无操作)的唯一要求变得清晰。这样,就无法保证有关填充位的任何信息 - 即使是 空指针 .

如此大的开销(37.5% 未使用位)的原因是 MSP430X 没有函数来 read/write 20 位甚至 24 位值(这会使数组索引非常昂贵)to/from记忆。只有一些常量可以是 20 位,因为它们使用包含 4 位的扩展字在指令中编码,其余 16 位与其他指令一样遵循 OP 代码。这可能是最后一个(小型)架构之一,显示在保持兼容性的同时需要为地址 space 扩展做多少额外的工作。

请注意,MSP430X 对于 20 位寻址模式有一些额外的缺陷。例如,中断处理程序必须驻留在较低的 64KiB 中,因为向量 table 仅包含 16 位条目。这实际上禁止向量 table 在 C 中定义为函数指针数组(因为它们不能自由地转换为任何其他函数指针并返回)。

C 标准不要求通过赋值复制填充位。赋值是根据值而不是表示来指定的。

N1570 6.2.6.2p5 说:

The values of any padding bits are unspecified.

这是一个不合格的陈述,暗示它们在所有情况下都是未指定的,即使在从设置了一些填充位的对象进行赋值之后也是如此。

就其本身而言,该声明可能被认为不够明确,无法确定填充位不一定被复制。

填充位对整数对象的表示没有贡献。引用句子的脚注说:

All other combinations of padding bits are alternative object representations of the value specified by the value bits.

("other"指陷阱表示。)

6.5.16.1p2,描述简单赋值,说:

In simple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand.

描述是根据而不是表示;没有暗示必须在 LHS 对象中维护 RHS 的表示。当然,赋值中的 RHS 可以是任意表达式,而不仅仅是对象引用。即使它只是一个对象的名称,它也会进行左值转换,如6.3.2.1p2所述;此转换仅指对象的值,而不是其表示。

(在其他地方,标准表示参数传递、函数参数传递和从函数返回值的行为类似于简单赋值。)