MSP430X架构是16位MSP430架构到20位地址空间的扩展。这是通过将处理器的寄存器扩展到20位来实现的,将最小可寻址单元保持在一个八位字节(CHAR_BIT
等于8)。
在此架构上,可以考虑使用8位char
、16位short
和模拟的32位long
来实现为int
提供20位整数类型的C编程语言。由于20不是CHAR_BIT
的倍数,因此在存储int
类型的变量时需要一些填充位。例如,可以将int
存储在四个字节中,留下一个字节和另一个字节的四位作为填充。
在阅读了关于整型中填充位的标准之后,我不确定它们应该如何表现。由于在这种情况下,填充只存在于存储中,因此它们的值既不能设置也不能观察,除非通过类型双关。即使这样,复制这种20位类型的对象也不会复制任何填充位。ISO 9899:2011是否允许这种填充位?
2条答案
按热度按时间kninwzqo1#
C标准不要求通过赋值来复制填充位。赋值是根据值而不是表示来指定的。
N1570 6.2.6.2p5说:
未指定任何填充位的值。
这是一个非限定语句,意味着它们在所有情况下都是未指定的,即使在从设置了一些填充位的对象进行赋值之后也是如此。
就其本身而言,该语句可能被认为足够模糊,以至于它没有牢固地建立填充位不一定被复制。
填充位对整数对象的表示没有贡献。引用的句子的脚注说:
填充位的所有其他组合是由值位指定的值的替代对象表示。
(The“其他”是指陷阱表示。)
6.5.16.1p2,描述简单赋值,说:
在 * 简单赋值 *(
=
)中,右操作数的值被转换为赋值表达式的类型,并替换存储在左操作数指定的对象中的值。描述是根据 * 值 * 而不是 * 表示 *;并不意味着RHS的表示必须保持在LHS对象中。当然,赋值中的RHS可以是任意表达式,而不仅仅是对象引用。即使它只是一个对象的名称,它也会经历 * 左值转换 *,如6.3.2.1p2所述;这种转换仅涉及对象的值,而不涉及其表示。
(在其他地方,标准说参数传递,函数参数传递和从函数返回值的行为类似于简单的赋值。
pdtvr36n2#
一般来说,标准对
sizeof
a类型有一些限制。基本约束是它必须是char
的倍数,其中sizeof(char)
定义为1
。有关类型中的填充位,请参阅6.2.6.1,它主要保留了 implementation defined 的表示。6.2.6.2p5声明未指定填充位的值;不需要保留,但是对填充位有两个重要的约束:
1.有符号整数中的正值应表示相同无符号类型的相同值。这保证了相同类型的有符号变量和无符号变量之间对于有符号变量范围内的正值的兼容性。
1.如果所有位都为零,则表示值
0
。因此,所有填充位也必须为0。然而,反过来是不正确的(感谢马特麦克纳布)。两个都包含填充位,因为它们是内部表示的一部分。从更实际的Angular 来看,除非存在奇偶校验等,否则填充位应被设置为零。取决于其它位的位(但必须满足第二约束)。
这是一个粗略的解释。有关详细信息,请参阅其余引用章节。
在MSP430 X上,20位
int
几乎没有实际用途。它们主要是为了扩展寻址范围,而不是为了整数算术(尽管指令集显然支持它-我在以前的编辑中错在这里)。指针有一个
sizeof
32位(4个8位字节),但只使用20位。一些嵌入式编译器可能支持特殊的short
/near
/...限定符,有效地提供两种不同的指针大小。然而,这实际上是违反标准的。(我有点矛盾:优化或可移植性)。MSP430 X是使用
stdint.h
(uintptr_t
)和stddef.h
(例如uintptr_t
)专用类型的平台之一。size_t
)是必不可少的,因为将指针转换到int
或从int
转换指针最终会失败。更重要的是,该标准对(u)intptr_t
(临时存储,无操作)的唯一要求变得清晰。这样,即使对于 * 空指针 *,也不能保证任何关于填充位的内容。造成这种大开销(37.5%未使用位)的原因是MSP430 X没有从内存读取/写入20位甚至24位值的功能(这会使阵列索引非常昂贵)。只有一些常数可以是20位,因为它们使用包括4位的扩展字编码在指令中,并且对于其他指令,剩余的16位跟随OP码。这可能是最后一个(小)架构,以显示有多少额外的努力,必须做的地址空间扩展,同时保持兼容性。
请注意,MSP430 X有一些额外的20位寻址模式的陷阱。例如,中断处理程序必须驻留在较低的64 KiB中,因为向量表仅包含16位条目。这实际上禁止在C中将vector表定义为函数指针数组(因为它们不能自由地转换为任何其他函数指针)。