如何在C++中输出以二进制形式存储的有符号整数-76?
如何让二进制数0b10110100表示-76而非180?
我正在学习用二进制优化程序,了解到补码(two’s complement)机制——二进制数1011 0100既可以表示180,也可以表示-76,取决于数据类型。但我想得到-76时,总是得到180,尝试用int8_t还报错:
error: narrowing conversion of ‘180’ from ‘int’ to ‘int8_t’ {aka ‘signed char’} [-Wnarrowing]
6 | int8_t num{0b1011'0100};
之前输出180的代码:
#include <iostream> using namespace std; int main(){ uint8_t num{0b1011'0100}; cout<<static_cast<int>(num); return 0; }
解决方法
方法1:先存无符号类型再强制转换
用uint8_t存储二进制值,再强制转换为int8_t,编译器会自动按补码规则解析为-76:
#include <iostream> #include <cstdint> using namespace std; int main(){ uint8_t num{0b1011'0100}; int8_t signed_num = static_cast<int8_t>(num); cout << static_cast<int>(signed_num) << endl; // 输出-76 return 0; }
方法2:用赋值代替列表初始化
列表初始化{}会严格检查数值范围,改用赋值操作可以绕过窄化转换检查,直接让编译器按补码解析8位二进制:
#include <iostream> #include <cstdint> using namespace std; int main(){ int8_t num; num = 0b1011'0100; // 赋值不触发窄化检查 cout << static_cast<int>(num) << endl; // 输出-76 return 0; }
报错原因说明
0b1011'0100作为整数字面量默认是int类型,值为180,而int8_t的取值范围是-128到127,180超出了这个范围。C++的列表初始化{}不允许这种可能丢失数据的窄化转换,因此报错。而赋值或先存uint8_t再转换,都是让编译器直接处理8位二进制的补码解析,不会触发范围检查。
内容的提问来源于stack exchange,提问作者Lkx8888
相关产品推荐
相关产品推荐

