按位或操作返回错误结果,求代码问题原因排查
问题根源:有符号
char的符号扩展 这个问题的核心在于MSVC(你用的MVS Community 2017)中char类型默认是有符号的,当它参与位运算时会触发符号扩展,导致结果不符合预期。
具体过程拆解
你的代码执行步骤里,问题出在n = n | arr[1];这一行:
arr[1]的值是0xc0,作为有符号char,它对应的十进制是-64(因为0xc0的最高位是1,是负数的补码表示)。- 当有符号
char参与运算时,会被自动提升为int类型。为了保持数值不变,编译器会进行符号扩展——把最高位(符号位)填充到int的高24位,所以0xc0就变成了0xffffffc0。 - 此时
n的值是0x0a00(uint16_t类型),也会被提升为int类型的0x00000a00。 - 两者按位或的结果是
0xffffffc0 | 0x00000a00 = 0xffffffc0,最后赋值给uint16_t的n时,会截断高16位,得到0xffc0,这就是你看到的错误结果。
解决方案
有几种简单的修复方式,任选其一即可:
1. 声明无符号char数组
直接把数组类型改成unsigned char,从根源避免符号扩展:
unsigned char arr[] = { 0x0a, 0xc0 }; uint16_t n{}; n = arr[0]; n = n << 8; n = n | arr[1]; // 此时n的值为0x0ac0,符合预期
2. 强制转换为无符号类型再运算
在使用arr[1]时,先强制转为unsigned char,截断符号扩展的部分:
char arr[] = { 0x0a, 0xc0 }; uint16_t n{}; n = arr[0]; n = n << 8; n = n | (unsigned char)arr[1]; // 强制转换后避免符号扩展
3. 使用明确的无符号8位整数类型
引入<stdint.h>头文件,用uint8_t定义数组,类型更清晰:
#include <stdint.h> uint8_t arr[] = { 0x0a, 0xc0 }; uint16_t n{}; n = arr[0]; n = n << 8; n = n | arr[1]; // 无符号类型不会触发符号扩展
内容的提问来源于stack exchange,提问作者Konstantin
相关产品推荐
相关产品推荐

