我们有以下代码行,我们知道它regF
是 16 位长、regD
8 位长和regE
8 位长、regC
3 位长并且假定为无符号:
regF <= regF + ( ( regD << regC ) & { 16{ regE [ regC ]} }) ;
我的问题是:移位会regD << regC
假设结果是 8 位,还是会因为&
16 位向量的按位而扩展到 16 位?
移位子表达式本身的宽度为 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 部分(或多或少)解释了这一点。如果你想要任何建议,那么永远不要写这样的表达式。防御性写作 - 将所有内容分解为单独的子表达式,然后组合子表达式。