C/C++学习笔记:按位运算基本知识及用法介绍

本文详细介绍了C/C++编程中的按位运算基础知识,包括按位与、或、非、异或操作及其应用,帮助读者理解这些运算符如何在二进制层面操作数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
 按位运算,见 C Primer Plus 中文第六版 第497页 
 
补码的概念:
在补码表示中,最高位为符号位,正数的符号位为0,负数为1
补码的规定如下:
对正数来说,最高位为0,其余各位代表数值本身(以二进制表示),如+42的补码为00101010。
对负数而言,把该数绝对值的补码按位取反,然后对整个数加1,即得该数的补码。如-42的补码为11010110(00101010按位取反11010101+1即11010110)
用补码来表示数,0的补码是单一的,都为00000000。(而在原码,反码表示中,+0和-0的表示是不单一的)。而且可以用111111表示-1的补(这也是补码与原码和反码的区别)。

 1、二进制反码或按位取反:~
 将1变为0,0变为1,例如:
 ~(10011010)计算之后得:
  (01100101) 

2、按位与:&
二元运算符&通过逐位比较两个运算对象,生成一个新值,对于每个相应的位,都为1时,结果才为1
例如: 
    (10010011)
   &(00111101)
-----------------
ans: 00010001
按位与运算符合计算后不再改变的变化规律:a & b & a = b & a & a

3、按位或:|
二元运算符按位或|,通过比较两个运算对象,生成一个新值,对于相应的位存在1,那么值为1
例如: 
    (10010011)
   |(00111101)
-----------------
ans: 10111111
按位或运算符合计算后不再改变的变化规律:a | b | a = b | a | a

4、按位异或:^
二元运算符按位异或^,逐位比较两个运算对象,对于一个相应位,如果只有一个1,那么值为1,否则值为0;
可以理解为:无进位相加,即不考虑进位的时候将对应值相加
例如: 
    (10010011)
   ^(00111101)
-----------------
ans: 10101110
异或运算符合交换律和结合律:
a ^ b = b ^ a;
a ^ a = 0;
0 ^ a = a;
a ^ b ^ a = b ^ a ^ a = b;
因此通常用来交换两个变量的值:例如交换a和b的值,我们可以这样计算:
a = a ^ b;
b = a ^ b;
a = b ^ a;
*/

/* 
常用算法之提取二进制中最右侧的1:
例如 获取 二进制数 010010101000 中最右侧的1,即获得 000000001000
解法:利用公式 a&(~a+1)即可 公式中的&和~都是按位运算符
a=           010010101000
~a=          101101010111
~a+1=        101101011000
b=a&(~a+1)=  000000001000
因此,按照此规律,可以处理原数的倒数第二个1:
a'=a-b=      010010100000
....周而反复,可以提取每一个1
*/

/* 
常用算法之 一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到这一个数:
例如 112222333344444444555 中5只出现了一次,则利用异或运算的规律,任何数对自己异或运算,结果均为0,即a ^ a = 0;
因此可以通过将所有值进行异或运算,即可获得5为出现奇数次的那个数。

*/

/* 
常用算法之 计算一个数字除以2:
只需要对它进行右移一位即可: (a / 2) == (a >> 1); 对正数负数都成立
*/


#include <iostream>
#include <cmath>
using namespace std;

void Bitewise_Negation(); //按位取反运算函数
void Bitewise_EXCLUSIVE_OR();//按位异或^运算函数
void Bitewise_OR(); //按位或|运算函数
void Bitewise_AND(); //按位与&运算函数

int main()
{
    Bitewise_EXCLUSIVE_OR();
    Bitewise_OR();
    Bitewise_AND();
    Bitewise_Negation();
    return 0;
}

void Bitewise_EXCLUSIVE_OR()//按位异或^运算函数
{
    int a = 5;
    int b = 6;
/* 我们来看看按位异或^实际运算过程
         (00000101)   //5的二进制
        ^(00000110)   //6的二进制
    -----------------
     ans: 00000011    //计算结果为3的二进制 
*/
    cout << "a = 5,b = 6,则(a ^ b) = " << (a ^ b) << endl;
    cout << "a = 5,b = 6,则((a ^ b) ^ a) = " << ((a ^ b) ^ a) << endl;
    cout << "a = 5,b = 6,则((b ^ a) ^ a) = " << ((b ^ a) ^ a) << endl;
    cout << "a = 5,b = 6,则(b ^ (a ^ a)) = " << (b ^ (a ^ a)) << endl;
    cout << "a = 5,b = 6,则((a ^ a) ^ b) = " << ((a ^ a) ^ b) << endl;
    cout << "a = 5,b = 6,则(a ^ b ^ a) = " << (b ^ a ^ a) << endl;
    cout << "a = 5,b = 6,则(b ^ a ^ a) = " << (b ^ a ^ a) << endl;    
    cout << "结论:按位异或运算符合分配律:a ^ b ^ a = b ^ a ^ a = b;" << endl;
    cout << "=================================" << endl; 
}
void Bitewise_OR() //按位或|运算函数
{
    int a = 5;
    int b = 6;
/* 我们来看看按位或|实际运算过程
         (00000101)   //5的二进制
        |(00000110)   //6的二进制
    -----------------
     ans: 00000111    //计算结果为7的二进制
*/
    cout << "a = 5,b = 6,则(a | b) = " << (a | b) << endl;
    cout << "a = 5,b = 6,则((a | b) | a) = " << ((a | b) | a) << endl;
    cout << "a = 5,b = 6,则((b | a) | a) = " << ((b | a) | a) << endl;
    cout << "a = 5,b = 6,则(b | (a | a)) = " << (b | (a | a)) << endl;
    cout << "a = 5,b = 6,则((a | a) | b) = " << ((a | a) | b) << endl;
    cout << "a = 5,b = 6,则(a | b | a) = " << (b | a | a) << endl;
    cout << "a = 5,b = 6,则(b | a | a) = " << (b | a | a) << endl;    
    cout << "结论:按位或运算符合计算后不再改变的变化规律:a | b | a = b | a | a ;" << endl;
    cout << "=================================" << endl;
}
void Bitewise_AND() //按位与&运算函数
{
    int a = 5;
    int b = 6;
/* 我们来看看按位与&实际运算过程
         (00000101)   //5的二进制
        &(00000110)   //6的二进制
    -----------------
     ans: 00000100    //计算结果为4的二进制
*/
    cout << "a = 5,b = 6,则(a & b) = " << (a & b) << endl;
    cout << "a = 5,b = 6,则((a & b) & a) = " << ((a & b) & a) << endl;
    cout << "a = 5,b = 6,则((b & a) & a) = " << ((b & a) & a) << endl;
    cout << "a = 5,b = 6,则(b & (a & a)) = " << (b & (a & a)) << endl;
    cout << "a = 5,b = 6,则((a & a) & b) = " << ((a & a) & b) << endl;
    cout << "a = 5,b = 6,则(a & b & a) = " << (b & a & a) << endl;
    cout << "a = 5,b = 6,则(b & a & a) = " << (b & a & a) << endl;    
    cout << "结论:按位与运算符合计算后不再改变的变化规律:a & b & a = b & a & a ;" << endl;
    cout << "=================================" << endl;
}

void Bitewise_Negation() //按位取反运算函数
{
    //int a = 2147483647; // 2^31 - 1 ; 
   
/* 我们来看看按位或|实际运算过程
        ~(00000101)   //5的二进制
    -----------------
     ans: 11111010    //计算结果为-6的二进制,对负数而言,把该数绝对值的补码按位取反,然后对整个数加1,即得该数的补码。
*/
    int sum = 0;
    int a = 0;
    cout << "sizeof(int) = " << sizeof(int) << endl;
    /*
    11111111111111111111111111111111 --> 2^30 + 2^29 + ...... + 2^1 + 2^0 
    */
    for (int i = 0; i < (sizeof(int) * 8 -1); i++)
    {
        a += pow(2,i);// a = a + pow(2,i);
    }
    cout << "2^30 + 2^29 + ...... + 2^1 + 2^0 = " << a << endl;
    cout << "2^30 + 2^29 + ...... + 2^1 + 2^0  + 1 = " << a + 1<< endl; // a + 1为负数
    cout << "经过计算,2147483647 + 1 = 2147483647,则就可以证明:int类型的最大值是2147483647,说明首位是符号位"<< endl;
    cout << "(unsigned int)pow(2,50) = " << (unsigned int)pow(2,50) << endl;// 最大值只能获取到2147483648
    cout << "(unsigned int)pow(2,32) = " << (unsigned int)pow(2,32) << endl;// 最大值只能获取到2147483648
    cout << "(unsigned int)pow(2,31) = " << (unsigned int)pow(2,31) << endl;// 最大值只能获取到2147483648
    cout << "(unsigned int)pow(2,30) = " << (unsigned int)pow(2,30) << endl;// 1073741824
/* 我们来看看按位或|实际运算过程
        ~(01111111111111111111111111111111)   //2147483647的二进制
    -------------------------------------------------------------------------------------
     ans: 10000000000000000000000000000000    //计算结果为-2147483648的二进制:对负数而言,把该数绝对值的补码按位取反,然后对整个数加1,即得该数的补码。

        ~(00000000000000000000000000000001)   //1的二进制
    -------------------------------------------------------------------------------------
     ans: 11111111111111111111111111111110    //计算结果为-2的二进制:对负数而言,把该数绝对值的补码按位取反,然后对整个数加1,即得该数的补码。
*/
    cout << "a = " << a << ",则 ~a = " << ~a << endl;
    cout << "a = " << a << ",则 ~a = " << ~~a << endl;

    cout << "对0取反:~0 = " << ~0 << endl; // 注意,在计算机中,没有-0
    cout << "对1取反:~1 = " << ~1 << endl; //对负数而言,把该数绝对值的补码按位取反,然后对整个数加1,即得该数的补码。
    cout << "对2取反:~2 = " << ~2 << endl; //对负数而言,把该数绝对值的补码按位取反,然后对整个数加1,即得该数的补码。
    cout << "对3取反:~3 = " << ~3 << endl; //对负数而言,把该数绝对值的补码按位取反,然后对整个数加1,即得该数的补码。
    cout << "对3取反:~4 = " << ~4 << endl; //对负数而言,把该数绝对值的补码按位取反,然后对整个数加1,即得该数的补码。
    cout << "对3取反:~5 = " << ~5 << endl; //对负数而言,把该数绝对值的补码按位取反,然后对整个数加1,即得该数的补码。

    //cout << "=================================" << endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

碧波bibo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值