我有一个功课问题(MIPS模拟器),例如我们需要采用16位“立即”值并对其进行符号和/或零扩展至32位。我的印象是,这可以通过强制转换轻松完成,例如:
uint32_t imm = (uint16_t)IMM_FIELD(instruction); # Zero extend to 32-bits
和
uint32_t imm = (int16_t)IMM_FIELD(instruction); # Sign extend to 32-bits
但后来我遇到了一段代码在线,在同一个项目上工作的人编写了自己的“sign_extension8to16”,“sign_extension16to32”函数,这些函数通过将8位数字右移7来评估是否有效或者不是最重要的位(现在在一个位置)是1,然后返回一个被转换为(uint16_t)的数字,相应地将高8位屏蔽为0或1。
这种方法真的有必要吗?我认为当然铸造已经解决了这个问题。我问的原因是我有非常奇怪的错误信息,我无法查明问题,所以我认为原因可能是我错误地归零并签署了扩展......
答案 0 :(得分:0)
IMO:你的方法会奏效。
让我们简化问题。
将uint16_t
推广到uint32_t
以及将int16_t
推广到int32_t
很容易理解,并且会出现预期的结果。零填充无符号整数和符号扩展有符号整数。
int main() {
uint16_t u = 65535;
int16_t i = -1;
printf("%" PRIu32 "\n", (uint32_t) u);
printf("%" PRId32 "\n", (int32_t) i);
return 0;
}
65535
-1
将int16_t
推广到uint32_t
会先将int16_t
推广到int32_t
,然后推广到uint32_t
。 (实际上我认为首先推广到int16_t
到int
到int32_t
然后再推广到uint32_t
如果sizeof int <= sizeof int32_t
。)因此代码会先进行符号扩展使结果成为无符号整数。
将uint16_t
升级为int32_t
会将uint16_t
直接宣传为int32_t
。一个简单的零扩展。
注意:我可以使用&#34;推广&#34;,当我应该说&#34;转换&#34;。
int main() {
uint16_t u = 65535;
int16_t i = -1;
printf("%" PRIu32 "\n", (uint32_t) i);
printf("%" PRId32 "\n", (int32_t) u);
return 0;
}
4294967295
65535