有符号数据转无符号数据时的符号位污染问题
https://www.cnblogs.com/xingce/p/18752703
问题背景
INT32 regValueLow = 0;
INT32 regValueHigh = 1;
regValueLow = 1 << 31;
UINT64 regValue = (((UINT64)regValueHigh) << 32) + (regValueLow); // 这段代码有什么问题?
上述代码会出现非预期的结果,当regValueLow 的符号位为1 时,将会污染UINT64的符号位,出现预期之外的数据。上述代码中 regValue = 0xFFFFFFFF80000000
有符号整数左移的未定义行为
regValueLow = 1 << 31; // 对 signed int 进行 31 位左移
当 1 被识别为有符号整型时,左移 31 位会导致符号位被置 1,产生负数(在 32 位系统中值为 -2147483648)。
C/C++ 标准规定,对有符号整数进行导致符号位变化的移位操作是未定义行为。
符号扩展污染高位数据
UINT64 regValue = ... + (regValueLow); // 用 signed 类型污染高位
当 regValueLow 是负数(如 -2147483648)时,转换为 64 位无符号整数会触发符号扩展,导致高 32 位被错误填充为全 1(例如 0xFFFFFFFF80000000 而非预期的 0x0000000080000000)。
修复方案:
UINT32 regValueLow = 0; // 改用无符号类型
UINT32 regValueHigh = 1; // 改用无符号类型
regValueLow = 1u << 31; // 明确使用无符号移位,或者强制转换到UINT32后再组合
UINT64 regValue = ((UINT64)regValueHigh << 32) | regValueLow; // 正确组合高低位