• [C++ 中的位操作]


    C++ 中的位操作

    定义二进制变量:

    一般是以八进制或者十六进制来定义,八进制数以0开头,十六进制数以0x开头

    例如int a = 0x80, 这里的80只能表示8个二进制位,它表示的是int的低8位,前面的24个二进制位补0,所以a = 128;也可以 a = –0x80, 此时a = -128;8进制同理

    需要注意的是:如果0x…能够在整形内表示,则其默认是int,否则再看unsigned int能否表示,接着long long ,再接着unsigned long long (可以用cout<<typeid(0xF0).name();查看变量类型)

    关于移位操作:

    << 左移位操作:从右边开始用0补空位

    >>右移位操作:对于无符号数从左边开始补0;对于有符号数,或者补符号位,或者补0,由编译器决定(gcc的编译器是补符号位)

    注意:移位的数目是负数或者移位出界时(最多只能移位类型二进制位大小-1),这个操作符的行为是未定义的,可以参考C++移位运算符,位操作只针对整数类型(int long等)或者char类型的数据

    常用二进制位操作(如果没强调,expr可以是无符号或有符号整数):具体请参考c_c++刁钻问题各个击破之位运算及其实例(2)

    1. 将expr的第n(n从0开始)位设置为1: expr |= (1<<n);

    2. 将expr的第n(n从0开始)位设置为0: expr &= (~(1<<n));

    3. 判断expr的第n(n从0开始)位是否为1:bool b = expr &(1<<n);

    4. 翻转expr的第n(n从0开始)位:expr ^= (1<<n);

    5. 将最右侧的1翻转成0:expr &= (expr-1) (可以用来判断二进制中1的个数,每次翻转一个1,知道数字变为0) 本文地址

    6. 向右连续传播最右侧的1位:expr |= (expr-1) (该操作使00101000 变为 00101111)

    7. 检查无符号数expr是否是2的整数次幂:if((expr&(expr-1))==0)return true; 即说明expr的二进制中只有一个1

    8. 将右侧的连续1位串翻转成0位串,其他保持不变:expr = ((expr|(expr-1))+1)&expr

    9. 检查无符号整数expr是否等于2的两个整数次幂之差 if(((expr|(expr-1))+1)&expr == 0)return true; (只要说明:无符号数二进制中所有的1都在一起)

    10. 对于整数expr,求最小的、比expr大的整数M,使得M与expr的二进制表示中有相同数目的1, 如下,具体可参考给力!高效!易懂!位运算求组合

    int NextN(int N)
    {
    int x = N&(-N);
    int t = N+x;
    return t | ((N^t)/x)>>2;
    }

    需要注意的是:如果没有比expr大且二进制中1相同的数,函数返回-1

    11. 循环移位,以整形举例,循环左移和右移函数如下

    int rotateLeft(int a, unsigned int n)//循环左移n位
    {
    n %= 32;
    if(n == 0)return a;
    return (a << n) | ((a & 0xFFFFFFFF) >> (32 - n));
    }

    int rotateRight(int a, unsigned int n)//循环右移n位
    {
    n %= 32;
    if(n == 0)return a;
    return ((a & 0xFFFFFFFF) >> n) | (a << (32 - n));
    }

    例如:

    a = 01111011,循环左移2位的正确结果是: b=11101101

    b = a >> (8 - 2); //用来得到正常左移丢失的位和循环移位后其正确位置 //b=00000001;

    a = a << 2; //a = 11101100

    a = a | b; //a = 11101101

    注意1:按照上面的例子,我们需要的是右移操作右边补0;但是如果输入是个负数,c++没有规定右移操作是怎么补位的,而大部分编译器是补符号位,所以此时需要把这个负数转化成无符号整数,这就是a & 0xFFFFFFFF的作用(0xFFFFFFFF的类型是unsigned int)

    注意2:当n 超过32时,需要n = n%32 这相当于循环移了好几圈;另外如果n = 0,那么32-n = 32,而整数移位操作对于大于31的移动位数是未定义的行为(见上面移位操作那部分红字注释)

    【版权声明】转载请注明出处http://www.cnblogs.com/TenosDoIt/p/3695166.html

  • 相关阅读:
    转 Unicdoe【真正的完整码表】对照表
    golang中,unsafe.sizeof到底是干嘛的?
    转载 Golang []byte与string转换的一个误区
    python异常处理--try except else raise finally
    微信静默授权增加浏览器历史记录导致跳转死循环的解决方案
    package-lock.json,我们应该了解
    webpack实现静态资源缓存的那点事
    webpack+babel项目在IE下报Promise未定义错误引出的思考
    CORS预检请求详谈
    谈谈form-data请求格式
  • 原文地址:https://www.cnblogs.com/wangdac/p/13164336.html
Copyright © 2020-2023  润新知