2

我们有以下代码行,我们知道它regF是 16 位长、regD8 位长和regE8 位长、regC3 位长并且假定为无符号:

regF <= regF + ( ( regD << regC ) & { 16{ regE [ regC ]} }) ;

我的问题是:移位会regD << regC假设结果是 8 位,还是会因为&16 位向量的按位而扩展到 16 位?

4

1 回答 1

6

移位子表达式本身的宽度为 8 位;移位的位宽始终是左操作数的位宽(参见 2005 LRM 中的表 5-22)。

然而,在那之后事情变得更加复杂。shift 子表达式作为运算符的操作数出现&&表达式的位长是两个操作数中最大的位长;在这种情况下,16 位。

这个子表达式现在显示为表达式的操作数+;这个表达式的结果宽度再次是 的两个操作数的最大宽度+,也就是 16。

我们现在有一个任务。这在技术上不是操作数,但使用相同的规则;在这种情况下,LHS 也是 16 位,因此 RHS 的大小不受影响。

我们现在知道整体表达式大小为 16 位;除了“自行确定”的操作数外,这个大小会向下传播到操作数。这里唯一的自定操作数是移位表达式 ( regC) 的 RHS,它没有被扩展。

现在确定表达式的符号。传播以同样的方式发生。由于我们至少有一个无符号操作数,这里的总体效果是表达式是无符号的,并且所有操作数都被强制为无符号。因此,在实际执行任何操作之前,所有(非自行确定的)操作数都被强制为无符号 16 位。

因此,换句话说,移位子表达式实际上以 16 位移位结束,尽管乍一看它似乎是 8 位。请注意,它不是16 位,因为 的 RHS&是 16 位,而是因为整个大小调整过程 - 表达式的宽度传播 - 得出的答案是 16。如果您分配给 18-bit reg,而不是 16-bit regF,那么您的移位将扩展到 18 位。

这一切都非常复杂且不直观,至少如果您对主流语言有任何经验的话。在 2005 LRM 的 5.4 和 5.5 部分(或多或少)解释了这一点。如果你想要任何建议,那么永远不要写这样的表达式。防御性写作 - 将所有内容分解为单独的子表达式,然后组合子表达式。

于 2014-04-27T21:17:22.007 回答