我们有以下代码行,我们知道regF
长16位,regD
长8位,regE
长8位,regC
是3位长并假设无符号:
regF <= regF + ( ( regD << regC ) & { 16{ regE [ regC ]} }) ;
我的问题是:移位regD << regC
是假设结果是8位还是会因为16位向量的按位&
而扩展为16位?
答案 0 :(得分:6)
shift子表达式本身的宽度为8位;移位的位宽始终是左操作数的位宽(参见2005 LRM中的表5-22)。
然而,事情变得更加复杂。 shift子表达式显示为&
运算符的操作数。 &
表达式的位长度是2个操作数中最大的一个的位长度;在这种情况下,16位。
此子表达式现在显示为+
表达式的操作数;此表达式的结果宽度再次是+
的两个操作数的最大宽度,再次为16.
我们现在有一项任务。这在技术上不是操作数,但使用相同的规则;在这种情况下,LHS也是16位,因此RHS的大小不受影响。
我们现在知道整体表达式大小是16位;这个大小会传播回操作数,除了自定义的&#39;操作数。这里唯一的自定义操作数是移位表达式(regC
)的RHS,它不会被扩展。
现在确定表达式的签名。传播以同样的方式发生。由于我们至少有一个无符号操作数,因此这里的整体效果是表达式是无符号的,并且所有操作数都被强制转换为无符号。因此,在实际执行任何操作之前,所有(非自定义)操作数都被强制转换为无符号16位。
因此,换句话说,移位子表达式实际上最终为16位移位,即使它看起来似乎是8位。请注意,它的不是 16位,因为&
的RHS是16位,但是,因为整个大小调整过程 - 宽度传播表达式 - 得出16的答案。如果您被分配到18位reg
而不是16位regF
,那么您的转变将扩展到18位。
这是非常复杂和非直观的,至少如果你有任何主流语言的经验。它(或多或少)在2005 LRM的5.4和5.5节中进行了解释。如果你想要任何建议,那么永远不要写这样的表达式。防御性地写 - 将所有内容分解为单个子表达式,然后组合子表达式。