C++右移运算符的一个小坑及解决

 更新时间:2025年09月10日 08:40:32   作者:玄黄问道  
文章指出右移运算符处理负数时左侧补1导致死循环,与除法行为不同,强调需注意补码机制以正确统计二进制1的个数

我遇到了这么一个函数

template<typename T>
unsigned char countByt(T byt)
{
    unsigned char num=0;
    while(byt)
    {
        num += (byt & 0x01);
        byt >>= 1;
        // cout<<hex<<byt<<endl;
    }
    return num;
}

很明显,这个函数是统计byt二进制下1的个数。

没毛病

但当我输入负数的时候,就会陷入死循环。

用那行注释中的东西输出中间过程:

由此可以看到

  • 非负数下,右移运算符,左面补0.
  • 负数下,右移运算符,左面补1.

我对代码进行如下修改:

template<typename T>
unsigned char countByt(T byt)
{
    unsigned char num=0;
    while(byt)
    {
        num += (byt & 0x01);
        byt/=2;
        //byt >>= 1;
        //cout<<hex<<byt<<endl;
    }
    return num;
}

负数的结果:

这个时候,统计的是其所对应正数的1的个数。

也很好理解

补码是其正数按位取反再加1

可以看到,一个数的正和负,它们最后一位一定是一样的!

1、如果我们用/=2来的话:

-1/2=0

那结果跟正数统计是一样的。

2、如果我们用>>=1的话:

-1:ffffffff

右移一位后,由于左侧补1,

还是:ffffffff

死循环就发生了。

但我在实验的时候又发现了有趣的一点:

    int n;
    while(cin>>n)
    {
        cout<<(n>>1)<<endl;

    }
1
0
-1
-1

2
1
-2
-1


3
1
-3
-2


9
4
-9
-5


8
4
-8
-4

可以看到:>>=1 等价于除以2后的(向下)取整。

而 / 运算符,是先对正数部分取整,再加符号。

因此对两个int变量a,b:

a/b不一定小于 等于(double)a/b;

    
    while(cin>>a>>b)
        cout<<((a/b)<=((double)a/b))<<endl;
        

输出:

5 3
1
-5 3
0
-5 -3
1
5 -3
0

总结

当使用右移运算符的时候,一定要注意输入为负数的可能!在负数下 >>1 和 /=2 并不等价!

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • C语言单链表贪吃蛇小游戏

    C语言单链表贪吃蛇小游戏

    这篇文章主要为大家详细介绍了C语言单链表贪吃蛇小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • 如何使用Qt实现实时数据动态绘制的折线图效果

    如何使用Qt实现实时数据动态绘制的折线图效果

    使用Qt的QChartView和定时器,本教程详细介绍了如何动态绘制折线图,通过定时器触发数据点的动态添加和坐标轴范围的自动调整,实现了实时更新数据的动态折线图应用,程序结合QLineSeries或QSplineSeries绘制折线或样条曲线,配合动画效果,展现数据变化
    2024-10-10
  • C语言版猜数字小游戏

    C语言版猜数字小游戏

    这篇文章主要为大家详细介绍了C语言版猜数字小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • 循环队列详解及队列的顺序表示和实现

    循环队列详解及队列的顺序表示和实现

    这篇文章主要介绍了循环队列详解及队列的顺序表示和实现的相关资料,需要的朋友可以参考下
    2016-12-12
  • C语言中的指针新手初阶指南

    C语言中的指针新手初阶指南

    指针是C语言的灵魂,精华之所在,指针强大而危险,用得好是一大利器,用得不好是一大潜在危害,下面这篇文章主要给大家介绍了C语言中指针的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2021-10-10
  • C++ 重载与重写的区别与实现

    C++ 重载与重写的区别与实现

    在面向对象语言中,经常提到重载与重写,本文主要介绍了C++ 重载与重写的区别与实现,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • visual studio 2022一个不易发现的问题

    visual studio 2022一个不易发现的问题

    本文主要介绍了visual studio 2022一个不易发现的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • C语言之栈和堆(Stack && Heap)的优缺点及其使用区别

    C语言之栈和堆(Stack && Heap)的优缺点及其使用区别

    本篇文章主要介绍了什么是栈(Stack) 、什么是堆( Heap),以及栈和堆的优缺点,同时介绍了应该什么时候使用堆和栈,有需要的朋友可以参考下
    2015-07-07
  • C语言开发实现扫雷游戏

    C语言开发实现扫雷游戏

    这篇文章主要为大家详细介绍了C语言开发实现扫雷游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • C++使用文件实现学生信息管理系统

    C++使用文件实现学生信息管理系统

    这篇文章主要为大家详细介绍了C++使用文件实现学生信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-01-01

最新评论