左移运算符(<<)结果不一致求助:变量i为何改变运算结果?
问题分析与解决
为什么两个printf输出不同?
C语言标准明确规定:移位运算符的右操作数必须是非负整数,且不能大于等于左操作数的位数。当右操作数为负数时,属于未定义行为——编译器可自由选择处理方式,甚至生成完全不可预测的结果。
你的实验中:
- 第一个表达式
2 << (i - 1),当i=0时,i-1是-1,触发未定义行为,编译器可能选择将结果置为0; - 第二个表达式
2 << (0 - 1),虽然计算结果也是-1,但编译器在编译期就能直接算出右操作数是负数,可能采用了另一种非标准处理逻辑(比如将负数位移当成循环移位),所以输出1。
这两种结果都是未定义行为的表现,没有统一规则可循,不能依赖这种行为编写正确代码。
二进制转十进制程序的修正
你的原代码除了负数位移问题,还有逻辑错误:
- 二进制字符串的权重计算错误:比如字符串"10",第一个字符'1'对应
2^1,但你的代码中i=0时会计算2 << (0-1),完全不符合权重逻辑; - 最终返回
9是测试残留,应返回计算好的result; - 可以用更简洁安全的方式实现:每次将结果左移1位(等价于乘以2),再加上当前位的数值。
修正后的代码:
#include <string.h> unsigned int binary_to_uint(const char *b) { unsigned int result = 0; int i, len; if (!b) return 0; len = strlen(b); for (i = 0; i < len; i++) { if (b[i] == '1') { result = result * 2 + 1; } else if (b[i] == '0') { result = result * 2; } else { // 遇到非0非1字符,返回0 return 0; } } return result; }
更简洁的写法:
#include <string.h> unsigned int binary_to_uint(const char *b) { unsigned int result = 0; if (!b) return 0; while (*b != '\0') { if (*b != '0' && *b != '1') return 0; result = (result << 1) | (*b - '0'); b++; } return result; }
代码说明
result << 1代替乘法,效率更高且写法直观;*b - '0'将字符'0'或'1'转换为整数0或1;- 遇到非二进制字符直接返回0,符合需求;
- 无负数位移操作,完全符合C语言标准,行为可预测。
内容的提问来源于stack exchange,提问作者user13871283
相关产品推荐
相关产品推荐

