十进制转二进制输出异常求助:两种C语言实现结果不符
问题分析与修复方案
嘿,我来帮你搞定这个问题~咱们先拆解下方法1出错的核心原因,再看看怎么修复。
错误根源:有符号整数的算术右移
你遇到的4294967295其实是32位无符号整数的最大值(也就是2^32-1),问题出在有符号整数的算术右移上:
- 当输入的
input是负数时,它的最高位(符号位)是1。 - 执行
input & (1<<i)(i是最高位索引)时,得到的是一个最高位为1的有符号int值——也就是负数。 - 对负数执行右移操作(
>>i)时,C语言会进行算术右移:用符号位(1)填充左侧空出的位,最终这个值会变成全1的int(比如32位下就是0xFFFFFFFF)。 - 最后用
%u格式符打印时,这个全1的有符号int会被解释为无符号整数,也就是4294967295。
另外还要提一句:1<<i当i是最高位时,对于有符号int来说其实是未定义行为(因为溢出了有符号整数的范围),虽然大部分编译器会按符号位处理,但这也是个隐患。
为啥方法2运行正常?
方法2里只是判断input & (1<<i)是否非零——不管这个结果是正还是负,只要非零就输出'1',否则输出'0'。它不需要对结果做右移操作,自然也就不会触发算术右移的问题,所以能正常工作。
修复方法1:改用无符号整数处理
把输入变量改成unsigned int,同时用无符号的1U来做移位操作,这样所有移位都是逻辑右移(填充0),就不会出现符号位的问题了:
#include <stdio.h> #include <limits.h> int main() { unsigned int input; scanf("%u", &input); for(int i = sizeof(unsigned int)*CHAR_BIT - 1; i >= 0; i--) printf("%u",(input & (1U << i)) >> i); return 0; }
修复方法2:强制转换为无符号后处理
如果还是需要用int类型接收输入,可以把input强制转换为unsigned int再处理:
#include <stdio.h> #include <limits.h> int main() { int input; scanf("%d", &input); unsigned int u_input = (unsigned int)input; for(int i = sizeof(int)*CHAR_BIT - 1; i >= 0; i--) printf("%u",(u_input & (1U << i)) >> i); return 0; }
修复方法3:单次计算时强制转无符号
也可以在打印前把运算结果强制转为无符号,避免算术右移的影响:
#include <stdio.h> #include <limits.h> int main() { int input; scanf("%d", &input); for(int i = sizeof(int)*CHAR_BIT - 1; i >= 0; i--) printf("%u", (unsigned int)(input & (1U << i)) >> i); return 0; }
内容的提问来源于stack exchange,提问作者Kona98
相关产品推荐
相关产品推荐

