C或C++取反操作(附代码及详解)
取反:~ 取反
按位取反,原来的位是1,就变为0,如果是0,就变为1
原码、反码和补码
原码:最高位是符号位,0表示正数,1表示负数
反码:最高为是符号位,0表示正数,1表示负数,正数的反码是它本身,负数的反码是除了符号位以外其余各位取反反码:最高为是符号位,0表示正数,1表示负数,正数的反码是它本身,负数的反码是除了符号位以外其余各位取反@TOC
补码:最高为是符号位,0表示正数,1表示负数,正数的补码是它本身,负数的补码是反码+1
为什么需要补码操作:
例如:1 + (-1) = 0
如果使用原码来直接计算 0001 + 1001 = 1010,计算的结果是-2,这样的结果是错误的
如果使用补码来计算 0001 + 1111 = 1 0000,最高位的1直接溢出,所以结果是0000,就是0
原码和补码的转化方式
补码转原码:正数不变,负数除了符号位以外,其余各位取反+1
原码转补码:正数不变,负数除了符号位以外,其余各位取反+1
为什么10取反之后会变为-11
因为计算机中存储方式都是按照补码的形式存储的,正数的补码是它本身,负数补码等于反码+1
所以10对应的二进制是0000 1010,取反之后1111 0101,最高位是1,代表符号位,说明这个数是负数,这是补码,如果要拿到十进制的结果,必须要将其转化为原码才能看到,原码是补码取反+1得来的,所以原码除了符号位以外,各位取反+1获取:1000 1010 + 1 = 1000 1011,这个值就是-11。
C语言表示
#include<stdio.h>// 引入标准输入输出库,用于使用printf函数打印结果intmain(){// 1. 无符号字符型变量的按位取反unsignedchar ch =0;// 定义无符号字符型变量ch,初始值为0// unsigned char是8位无符号整数(范围0~255),没有符号位,所有位都用于表示数值// 此时ch的8位二进制为:0000 0000(每一位都是0) ch =~ch;// 对ch进行按位取反操作(~是按位取反运算符)// 按位取反规则:二进制的每一位0变1,1变0// 原来的二进制:0000 0000// 取反后变为:1111 1111(8位全是1)// 对于无符号数,11111111转换为十进制是255(计算:128+64+32+16+8+4+2+1=255)printf("%d\n", ch);// 打印ch的值,输出255// 2. 有符号整型变量的按位取反int number =10;// 定义有符号整型变量number,初始值为10// int是32位有符号整数(部分系统是64位,这里以32位为例)// 有符号数的最高位是符号位(0表示正数,1表示负数),其余位表示数值// 10的32位二进制(原码):00000000 00000000 00000000 00001010 number =~number;// 对number进行按位取反操作// 按位取反后,每一位0变1,1变0,结果为:// 11111111 11111111 11111111 11110101// 此时最高位是1,表示这是一个负数// 计算机中负数用补码表示,要得到十进制值需转换为原码:// 补码转原码步骤:先取反(符号位不变),再加1// ① 补码:11111111 11111111 11111111 11110101// ② 取反(符号位不变):10000000 00000000 00000000 00001010// ③ 加1:10000000 00000000 00000000 00001011(即-11)printf("%d\n", number);// 打印number的值,输出-11return0;}C++
#include<iostream>#include<bitset>// 用于将整数转换为二进制字符串usingnamespace std;intmain(){// 1. 无符号整数的按位取反(unsigned int)unsignedint u_num =5;// 无符号数5unsignedint u_result =~u_num;// 按位取反操作 cout <<"=== 无符号整数的按位取反 ==="<< endl;// 用bitset<8>显示8位二进制(简化观察,实际是32/64位) cout << u_num <<" 的二进制:"<< bitset<8>(u_num)<< endl;// 00000101 cout <<"取反后二进制:"<< bitset<8>(u_result)<< endl;// 11111010 cout <<"取反后的值:"<< u_result << endl << endl;// 250(8位情况下)// 2. 有符号整数的按位取反(int)int s_num =5;// 有符号数5int s_result =~s_num;// 按位取反操作 cout <<"=== 有符号整数的按位取反 ==="<< endl; cout << s_num <<" 的二进制:"<< bitset<8>(s_num)<< endl;// 00000101(正数原码) cout <<"取反后二进制:"<< bitset<8>(s_result)<< endl;// 11111010(负数补码) cout <<"取反后的值:"<< s_result << endl;// -6(补码转十进制的结果)// 3. 特殊案例:对0进行取反int zero =0; cout <<"\n=== 对0进行按位取反 ==="<< endl; cout << zero <<" 的二进制:"<< bitset<8>(zero)<< endl;// 00000000 cout <<"取反后二进制:"<< bitset<8>(~zero)<< endl;// 11111111 cout <<"取反后的值(有符号):"<<~zero << endl;// -1(32位下是-1) cout <<"取反后的值(无符号):"<<(unsignedint)~zero << endl;// 4294967295(32位无符号最大值)return0;}