admin管理员组文章数量:1794759
进制转换和位操作(详细,通俗,易懂)
13.进制转换 13.1.明确:计算机中数字都是在内存中,并且数字都是以二进制的形式存储 13.2.明确:计算机中对数字的表示形式有四种: 2进制表示,8进制表示,10进制表示,16进制表示 不管是哪种形式,都是对同一个内存中存储的数字的不同表示形式而已 也就是内存的中的数字不会随着进制的不同而改变! 类似:人(数字):在家(2进制) 在学校(8进制) 在公司(10进制) 在那种地方(16进制) 人不管在哪里,人的长相不会变! 8,10,16进制给程序员看,好看 2进制给计算机看,计算机只认2进制 13.3.明确:计算机中把内存中每个字节又分8段,每段只能记录0和1 要想把一个数字存储到内存中,必须将这个数字分拆成若干个0和1 每段对应的专业术语:位,bit,bit位 结论:1Byte=8bit 2Byte=16bit 4Byte=32bit 8Byte=64bit 例如:char a = ‘a’; //需要1个字节,8位就可以存97 short b = 2500; //需要2字节,16位就可以2500 int c = 2500000000000; //需要4字节,32位就可以存 13.4.二进制 切记切记切记:计算机中所有的数字都是以二进制的形式存储到内存中 a)定义:用一组0和1表示数字的方法简称二进制表示形式 例如:现在有一个10进制数90(前提是char类型),要存储到内存中,必须以二进制来存 需要将90分拆成8位,其二进制表示形式为:01011101(二进制形式) b)特点: 1.二进制数的编号:从0开始 例如:前提是char类型 高位 低位 76543210 二进制数的编号 01011010 二进制数 例如:前提是short类型 高位 低位 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 二进制数的编号 0 1 1 1 0 1 1 0 0 0 0 1 1 0 0 1 二进制数 2.二进制数中每个1单独代表一个10进制数字,这个数字的值是2的编号次方 例如:前提是char类型 高位 低位 76543210 二进制数的编号 01000000 二进制数A(其中第6位的1对应的数字为2的6次方=64) 3.二进制数中相邻的两个1,左边是右边的2倍 4.二进制数加1的时候把编号为0位置开始的多个连续的1变成0,最左边的0变1 例如: 76543210 二进制数的编号 00001111 + 1 = 00010000 01111110 + 1 = 01111111
13.5.二进制和十进制之间的转换 a)明确:计算机中所有的数字都是以二进制的形式存储到内存中 而这个10进制就是对内存中的二进制数的另一个表达方式而已,不会改变原来的数 b)二进制表示的非负数(0和正数)转换成10进制就是把每个二进制数中的1单独换算然后加 例如:前提是char类型 76543210 二进制数的编号 01101010 二进制数A(非负数) A对应的十进制数B=2的6次方+2的5次方+2的3次方+2的1次方=64+32+8+2=106 结论:将来把106十进制数分拆8位,一位一位的存到1字节的内存中 c)10进制表示的非负数转2进制 采用"除2取余,逆序排列"法 具体做法是:用2整除十进制整数,可以得到一个商和余数; 再用2去除商,又会得到一个商和余数,如此进行,直到商为小于1时为止, 然后把先得到的余数作为二进制数的低位 后得到的余数作为二进制数的高位,依次排列起来。 例如:91这个十进制数转成对应的二进制 91/2=45 余1 45/2=22 余1 22/2=11 余0 11/2=5 余1 5/2=2 余1 2/2=1 余0 1/2=0 余1 结果二进制为:01011011
789/2=394 余1 第0位 394/2=197 余0 第1位 197/2=98 余1 第2位 98/2=49 余0 第3位 49/2=24 余1 第4位 24/2=12 余0 第5位 12/2=6 余0 第6位 6/2=3 余0 第7位 3/2=1 余1 第8位 1/2=0 余1 第9位 789的二进制数:000001100010101(用2个字节来存储,高5位补0)
d)负数的十进制和二进制不能直接转换,必须借助相反数(5的相反数-5) 1.十进制的负数转二进制三步骤: 首先计算相反数 然后将相反数转成二进制 最后取反加1(取反的意思就是1变0,0变1) 例如:-14(10进制的负数,前提是数据类型为char) 1.计算-14的相反数14 2.将14转换成二进制:00001110 3.取反加1:11110001+1=11110010 结论:-14将来在内存中对应的二进制数为11110010 2.明确:有符号类型数字(不加unsigned)才能有符号 二进制数中最左边的位叫做符号位 此位可以确定数字的符号(正还是负) 符号位的值为0表示此数字为非负数(0和正数) 符号位的值为1表示此数字为负数 切记:讨论符号位的前提是必须确定数据类型 例如:10010101(前提是这个二进制数的数据类型为char),此数必然是负数 00010101(前提是这个二进制数的数据类型为char),此数必然是正数 1001010110010101(前提是这个二进制数的数据类型为short),此数必然是负数 0001010110010101(前提是这个二进制数的数据类型为short),此数必然是正数 0000000010010101(前提是这个二进制数的数据类型为char),此数必然是负数 例如:换算二进制数10110110的十进制(前提是数据类型为char,显然为负数) 1.先取反加1:01001001+1=01001010 2.然后将二进制转十进制:01001010=2的6次方+2的3次方+2的1次方=64+8+2=74 3.最后取相反数:-74
13.6.二进制(0/1)和八进制(0~7)之间的转换 a)明确:计算机中所有的数字都是以二进制的形式存储到内存中 而这个8进制就是对内存中的二进制数的另一个表达方式而已,不会改变原来的数 b)八进制定义:就是把二进制数从右边到左边每三位分一组 每组用一个0到7的数字替换得到八进制表示形式 注意:八进制数前面加0(零) 占位符:0%o 例如:二进制数:0110 1001(十进制为105),转八进制,三步骤: 1.先分组:001 101 001 2.换算: 001=2的0次方=1 101=2的2次方+2的0次方=5 001=2的0次方=1 3.替换:0151
重磅好消:二进制,十进制,八进制之间的转换实际开发记得用计算器!
13.7.二进制(0/1)和十六进制(0~f)之间的转换(核心中的核心) a)明确:计算机中所有的数字都是以二进制的形式存储到内存中 而这个16进制就是对内存中的二进制数的另一个表达方式而已,不会改变原来的数 b)十六进制定义:把二进制数从右边到左边每四位分为一组 每组用一个字符替换(用a到f之间的字母替换10~15之间的数字) 注意:16进制数前面加0x或者0X,不用区分大小写 占位符:%#x或者%#X 例如:11000011(二进制),转成对应的16进制数,分三步: 1.先分组:1100 0011 2.换算: 1100=2的3次方+2的2次方=12 0011=2的1次方+2的0次方=3 3.替换 12->c 3->3 4.结果:此二进制对应的十六进制为:0xC3
13.8.切记切记切记:务必拿下二进制和十六进制之间的转换 二进制在程序中一般用16进制表示,16进制也就是二进制 严重鄙视用计算器实现2进制和16进制的转换,必须立马脑子换算出来! 结论: 16进制 2进制 0 0000 1 0001 2 0010 3 0011 4 0100 5 0101(用的多) 6 0110 7 0111 8 1000 9 1001 a 1010(用的多) b 1011 c 1100 d 1101 e 1110 f 1111 演练: 高 低 0x48 0100 1000 0xb6 1011 0110 高 低 0xfacb6321 1111 1010 1100 1011 0110 0011 0010 0001 0x5a48cd17 0101 1010 0100 1000 1100 1101 0001 0111 ----------------------------------------------------------------------- 位操作 4.6.逻辑(真真假假,假假真真)运算符 a)明确:计算机中的真就是非0(包括1),0就是假 逻辑运算符作用:实现计算机程序中的逻辑判断 例如:当用户名和密码都对了,才能登陆 登陆方式可以是微信或者手机号后者抖音号等 b)逻辑运算符类型:三类 1.逻辑与: &&(并且,与此同时的意思) 2.逻辑或: ||(或者的意思) 3.逻辑非: !(对着干的意思) c)逻辑与&&运算符特点 使用语法:C=表达式A && 表达式B 语义:只有当A和B的值都为真(非0),整个表达式C的值才为真 只要有一个为假,整个表达式C的值都为假 例如:1 && 1; //整个表示式结果为真 0 && 1; //假 1 && 0; //假 0 && 0; //假 d)逻辑或||运算符特点 使用语法:C=表达式A || 表达式B 语义:只要A和B中有一个为真,整个表达式C的值都为真 只有当A和B都是假,结果才能是假 例如:0 || 0; //假 1 || 0; //真 0 || 1; //真 1 || 1; //真 e)逻辑非运算符特点 使用语法:!表达式A 语义:A假结果为真,A真结果为假 例如: !1;//结果为假 !0;//结果为真 f)切记:短路运算(笔试题必考) 形式1.A && B:如果A的值为假,则B不处理,B的代码不执行 例如: int a = 1; 0 && ++a; printf(“a = %d\\n”, a); //a=1
int b = 1; 250 && ++b; printf(“b = %d\\n”, b); //b=2
形式2.A || B: 如果A的值为真,则B不处理,B的代码不执行 例如: int a = 1; 0 || ++a; printf(“a = %d\\n”, a); //a=2
int b = 1; 250 || ++b; printf(“b = %d\\n”, b); //b=14.7.位(bit)运算符 a)计算机中所有的数据(数字)都是内存中,并且都是以二进制的形式存放(1或者0,bit位) 而8,10,16进制仅仅是对二进制数的一种人为的友好表示形式(给人看的) b)位运算符作用:位运算就是对内存中的二进制数进行运算,并且C语言专门提供对应的 运算符,简称位运算符 c)位运算符四种形式: 位与:&(清0) 位或 : |(置1) 位异或: ^(反转) 位反: ~(取反) d)位与运算符特点: 1.语法:C = A & B; 例如: A: 01011010 0x5a B: 11100011 0xe3 &------------------- C: 01000010 0x42 2.规律:任何数跟0做位与,结果为0,任何数跟1做位与,保持原值 3.切记切记切记应用场合:一般用于将某个数的某个bit位清0,并且保持其他位不变 例如:将0x5a这个数的第3位清0: 0x5a & 0xf7 76543210 二进制编号 A:0x5a 01011010 B : 0xf7 11110111 C: 0x52 01010010
例如:将0x5a这个数的第3位和第4位清0: 0x5a & 0xE7 76543210 二进制编号 A:0x5a 01011010 B : 0xE7 11100111 C: 0x42 01000010e)位或运算特点 1.语法格式:C = A | B; 例如: A: 01011010 0x5a B: 11100011 0xe3 |------------------- C: 11111011 0xfb 2.规律:任何数跟1做位或,结果为1,任何数跟0做位或,保持原值 3.切记切记切记应用场合:一般用于将某个数的某个bit位置1,并且保持其他位不变 例如:将0x5a这个数的第2位置1: 0x5a | 0x04 76543210 二进制编号 A:0x5a 01011010 B : 0x04 00000100 C: 0x5e 01011110 例如:将0x5a这个数的第1,2位置1: 0x5a | 0x06 76543210 二进制编号 A:0x5a 01011010 B : 0x06 00000110 C: 0x5e 01011110
f)位异或运算特点:^ 1.语法:C = A ^ B; 例如: A: 01011010 0x5a B: 11100011 0xe3 ^------------------- C: 10111001 0xb9 2.规律:相同为0,不同为1,应用于取反场合
g)位反运算符特点:~ 1.语法:C=~A; 例如: A: 01011010 0x5a ~A:10100101 0xa5 2.规律:0变1,1变0 3.注意:位反(~)运算符一般和位与(&)结合起来实现将某个数的某个bit清0操作
4.8.移位运算符 a)功能:就是将二进制数统一向左或者向右移动n个位置(简称左移,右移) b)移位运算符种类:两种 左移:A<<B 语义:将A左移B个位置 右移 : A>>B 语义:将A右移B个位置
例如: 1 << 3:将1左移3位 3 >> 1:将3右移1位 c)移位运算符特点: 1.向左移动后右边空出来的数据用0来填充 例如:A数据前提是char类型 A=0x5A = 01011010 A << 2 = 01011010 << 2 结果为: 01101000 = 0x68 2. 无符号类型数字右移时左边空出来的数据用0来填充 例如:01011010 >> 2 结果为:00010110 = 0x16 3.有符号类型数字右移时左边空出来的数据用符号位填充 例如:10100101(前提是char类型) >> 2 结果为: 11101001 = 0xE9 4.左移n位相当于乘以2的n次方 5.右移n位相当于除以2的n次方
d)切记切记切记: 1.重点掌握左移 2.如果程序中将来涉及乘或者除2的n次方运算,务必用左移或者右移(高薪) 严重鄙视用*或者/,因为后者的执行效率相当低下! 例如: int a = 1; int b = a * 4; //垃圾代码 int b = a << 2; //高薪代码 3.不管是位运算符(&,|,^,~)还是左移,右移他们都不会改变变量本身的值! 例如: int a = 3; int b = a << 1; printf(“a = %d, b = %d\\n”, a, b); //a = 3, b = 6
e)切记实际开发常用的位操作公式: 需求就两个: 清0公式: 1.将某个变量的某1个位清0,其他位保持不变 A &= ~(1 << 位编号); //类似:A = A & ~(1 << 位编号) 2.将某个变量的某2个连续的位清0,其他位保持不变 A &= ~(3 << 位编号); 3.将某个变量的某3个连续的位清0,其他位保持不变 A &= ~(7 << 位编号); 4.将某个变量的某4个连续的位清0,其他位保持不变 A &= ~(0xF << 位编号);
置1公式: 1.将某个变量的某1个位置1,其他位保持不变 A |= (1 << 位编号); 2.将某个变量的某2个连续的位置1,其他位保持不变 A |= (3 << 位编号); 3.将某个变量的某3个连续的位置1,其他位保持不变 A |= (7 << 位编号); 4.将某个变量的某4个连续的位置1,其他位保持不变 A |= (0xF << 位编号);
提示:公式推导流程 31 15 7 0 1 << 0 0000 0000 0000 0000 0000 0000 0000 0001 //0x1 1 << 1 0000 0000 0000 0000 0000 0000 0000 0010 //0x2 1 << 2 0000 0000 0000 0000 0000 0000 0000 0100 //0x4 1 << 3 0000 0000 0000 0000 0000 0000 0000 1000 //0x8 1 << 4 0000 0000 0000 0000 0000 0000 0001 0000 //0x10 … 变形: 31 15 7 0 ~(1 << 0) 1111 1111 1111 1111 1111 1111 1111 1110 ~(1 << 1) 1111 1111 1111 1111 1111 1111 1111 1101 ~(1 << 2) 1111 1111 1111 1111 1111 1111 1111 1011 ~(1 << 3) 1111 1111 1111 1111 1111 1111 1111 0111 ~(1 << 4) 1111 1111 1111 1111 1111 1111 1110 1111 … 现在有一个数据为0x5A: 0000 0000 0000 0000 0000 0000 0101 1010 要求将0x5A的第0位(bit0)清0,其余位保持不变: 0000 0000 0000 0000 0000 0000 0101 1010 &1111 1111 1111 1111 1111 1111 1111 1110 = ~(1 << 0) 结果:0x5A & 0xFFFFFFFE //垃圾,可读性很差 0x5A & ~(1 << 0) //可读性很好
要求将0x5A的第1位(bit1)清0,其余位保持不变: 0000 0000 0000 0000 0000 0000 0101 1010&1111 1111 1111 1111 1111 1111 1111 1101 = ~(1 << 1) 结果:0x5A & 0xFFFFFFFD //垃圾,可读性很差 0x5A & ~(1 << 1) //可读性很好
要求将0x5A的第0位(bit1)置1,其余位保持不变: 0000 0000 0000 0000 0000 0000 0101 1010 | 0000 0000 0000 0000 0000 0000 0000 0001 = (1 << 0) 结果:0x5A | 0x1 //垃圾,可读性很差 0x5A | (1 << 0) //可读性很好 要求将0x5A的第1位(bit1)置1,其余位保持不变: 0000 0000 0000 0000 0000 0000 0101 1010 | 0000 0000 0000 0000 0000 0000 0000 0010 = (1 << 1) 结果:0x5A | 0x1 //垃圾,可读性很差 0x5A | (1 << 1) //可读性很
目的:要求将b的4,5,6,7,8位清0 int b = 0x12345678; b &= ~(0x1F << 4); b = b & ~(0x1F << 4); 0x1F: 0000 0000 0000 0000 0000 0000 0001 1111 0x1F << 4: 0000 0000 0000 0000 0000 0001 1111 0000 ~(0x1F << 4): 1111 1111 1111 1111 1111 1110 0000 1111 b=0x12345678; 0001 0010 0011 0100 0101 0110 0111 1000 0x12345678 & ~(0x1F << 4): 1111 1111 1111 1111 1111 1110 0000 1111 &0001 0010 0011 0100 0101 0110 0111 1000 0001 0010 0011 0100 0101 0110 0000 1000 //结果:0x12345608 8 7654 目的:要求将b的4,5,6,7,8位置1 int b = 0x12345678; b |= (0x1F << 4); b = b | (0x1F << 4); 0x1F: 0000 0000 0000 0000 0000 0000 0001 1111 0x1F << 4: 0000 0000 0000 0000 0000 0001 1111 0000 b=0x12345678; 0001 0010 0011 0100 0101 0110 0111 1000 0x12345678 | (0x1F << 4): 0000 0000 0000 0000 0000 0001 1111 0000 &0001 0010 0011 0100 0101 0110 0111 1000 0001 0010 0011 0100 0101 0111 1111 1000 //结果:0x123457F8
4.9.取地址运算符&和解引用运算符* a)明确地址特性:计算机中地址由32位二进制数组成,也就是一个地址32位,4字节 b)取地址运算符&作用:获取一个变量在内存对应的首地址 占位符%p用来显示地址信 c)取地址运算符&使用语法格式:&变量名; 例如: int a = 250; //分配4字节内存空间并且放一个250数字 printf(“变量a的首地址为%p\\n”, &a); d)解引用运算符作用:根据变量的首地址获取内存中的数据 或者根据变量的首地址向内存写入新数据 e)解引用运算符语法是:*地址 结果可以操作内存了 例如: int a = 250; printf(“a的首地址%p\\n”, &a); printf(“a的值是%d\\n”, *&a); //通过地址获取变量的值 *&a = 520; //根据变量a的地址找到a的内存,然后向内存写入一个新数520
4.10.条件运算符(又称三目运算符) a)语法格式:整个表达式结果D = 条件表达式A ? 表达示B : 表达式C 语义:如果A为真,D=表达式B的运算结果,否则D=表达式C的运算结果 例如: int a = 1 ? 2 : 3; //a=2
案例:输入一个负数,求它的绝对值
4.11.注意运算符的优先级 例如: printf("%d\\n", 2+3*2); //8 printf("%d\\n", (2+3)*2); //10 结论:()它的优先级最高,不嫌多
例如: int a; a = 1 > 2 && 2 < 3; 等价于: a = (1 > 2) && (2 << 3);版权声明:本文标题:进制转换和位操作(详细,通俗,易懂) 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1686574016a83437.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论