You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

左移运算符(<<)结果不一致求助:变量i为何改变运算结果?

问题分析与解决

为什么两个printf输出不同?

C语言标准明确规定:移位运算符的右操作数必须是非负整数,且不能大于等于左操作数的位数。当右操作数为负数时,属于未定义行为——编译器可自由选择处理方式,甚至生成完全不可预测的结果。

你的实验中:

  • 第一个表达式2 << (i - 1),当i=0时,i-1是-1,触发未定义行为,编译器可能选择将结果置为0;
  • 第二个表达式2 << (0 - 1),虽然计算结果也是-1,但编译器在编译期就能直接算出右操作数是负数,可能采用了另一种非标准处理逻辑(比如将负数位移当成循环移位),所以输出1。

这两种结果都是未定义行为的表现,没有统一规则可循,不能依赖这种行为编写正确代码。

二进制转十进制程序的修正

你的原代码除了负数位移问题,还有逻辑错误:

  1. 二进制字符串的权重计算错误:比如字符串"10",第一个字符'1'对应2^1,但你的代码中i=0时会计算2 << (0-1),完全不符合权重逻辑;
  2. 最终返回9是测试残留,应返回计算好的result;
  3. 可以用更简洁安全的方式实现:每次将结果左移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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 07:15:44