代码是否正确实现16位转32位有符号整数的符号扩展?
问题分析与解答
你的代码没有正确实现符号扩展,具体原因和修正方案如下:
核心问题点
- 你用
unsigned char类型的字节拼接出的16位值,在赋值给int value时是零扩展而非符号扩展:memory[address+1]是无符号字符,左移8位后高位会被填充0;和低8位做|运算后得到的value,本质是把这两个字节当成无符号16位整数处理。将其赋值给int32_t时,只会把16位值的高位补0,不会根据原16位值的符号位(第15位)填充1。 - 关于
int32_t的填充:int32_t确实是32位有符号整数,但前提是你要先把16位值当成有符号16位整数,才能在转换为32位时自动触发符号扩展。直接用无符号字节拼接的结果转int32_t,只会做零扩展。
修正方案
要实现正确的符号扩展,需先把拼接后的16位值显式声明为有符号16位类型(int16_t),再赋值给int32_t:
#include <stdint.h> // 需包含头文件以使用int16_t/int32_t void store_data(unsigned char* data){ int param1 = 5; int param2 = 6; int address = array_of_ints[param2] + 50; // 先拼接为有符号16位整数 int16_t signed_16bit = (int16_t)(memory[address] | (memory[address+1] << 8)); int32_t sign = signed_16bit; // 自动触发符号扩展,将16位符号位扩展至32位 array_of_ints[param1] = sign; }
更严谨的写法(规避移位时的类型提升问题):
int16_t signed_16bit = (int16_t)(((uint16_t)memory[address+1] << 8) | memory[address]);
补充说明
如果memory是char*而非unsigned char*,逻辑会有所不同——但你明确说明它是存储字节值的unsigned char*数组,因此必须显式转换为有符号16位类型才能触发符号扩展。
内容的提问来源于stack exchange,提问作者HyperCoderSuperion
相关产品推荐
相关产品推荐

