操作符详解
正数的原码反码补码相同
负数的原码最高位数是1,正数为0
整数在内存中存储的是补码
负数的左移与右移,移的是补码,打印的是源码
补码-1取反就是原码。
左移有乘2的效果
左移和右移只针对整数。
vs里的右移操作赋采用的是算数右移,右边丢弃、左边补原符号位
符号位是根据正数还是负数来确定的,正数补0,负数补1.
总结:
计算的是以补码形式计算,打印的是以原码形式存在。
计算的时候要用补码,因为整数在内存中存储的是补码。
按位与二个同时为1就得1,有一个不得1就为0.
取反的时候不要动符号位。
异或是相同为0,相异为1
0异或a是a a异或a是0
异或支持交换律
统计二进制中有多少个1
任何一个数a按位与1如果==1就说明a的二进制最低位是1
a&1==0 说明a的二进制最低位是0
就比如这段二进制代码 a&1 第1位是0 就&1 得0 就跳过最低位,看第二位,如果第二位&1等于1就让COUNT++,一直循环下去。这样就可以知道这段二进制代码有多少个1了。
方法1 利用&和>>操作符计算出二进制代码有多少个1.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{int i = 0;int a = 0;while (~scanf("%d", &a)){int count = 0;for (i = 0; i < 32; i++){if ((a >> i) & 1 == 1){count++;}}printf("%d\n", count);} return 0;
}
总结
把一个二进制向右移动i个位移到最低位和1进行按位与进行比,如果==1就说明二进制有1
从右往左看,每次移到的位位数再增加,最高是32位
方法2:利用/2 %2的方法来
、
想得到二进制的每一位 /2 %2来解决这个问题
//考虑正负数问题
int count_one_bit(unsigned int n)
{int count = 0;while (n){if ((n % 2) == 1){count++;}n /= 2;}return count;
}
int main()
{int n = 0;scanf("%d", &n);int ret=count_one_bit(n);printf("%d\n", ret);return 0;
}
方法3
利用n=n&(n-1)来达到把n的二进制最右边的1去掉
比如n=-1
1111 n
1110 n-1
1110 n
1101 n-1
1100 n
1011 n-1
1000 n
0111 n-1
0000 n
利用这种效果来实现二进制代码有多少个1
//判断一个数是否是2的次方数
//判断一个数的是否是2的次方数
//n=n&(n-1)
// 0001
//0010
//0100
//1000
int main()
{int n = 0;scanf("%d", &n);if ((n & (n - 1)) == 0){printf("YES\n");}else{printf("NO\n");}return 0;
}
练习2 二进制位 置0或者置 1
编写代码将13⼆进制序列的第5位修改为1,然后再改回0?
//编写代码将13⼆进制序列的第5位修改为1,然后再改回0 ?
// 0001 1101
int main()
{int n = 0;scanf("%d", &n); // 13 0000 1101 //移到n = n | (1 << 4); // 0000 1101 | 0001 0000==0001 1101printf("%d\n", n);//复原
// 0001 1101 变成 0000 1101
// 按位与1110 1111 即可 怎么变呢 1的二进制是 0000 0001 左移4位 0001 0000然后取反 1110 1111n = n & ~(1 << 4);printf("%d\n", n);return 0;
}
获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列
总结方法:
输入的数只要往右移,把每一个数移到最低位按位与上一个1就可以获得最低的是否是1了,可以明确判断出你输入的数转换成二进制形式有多少个1.
编程实现:两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同
语法说说支持连续赋值,建议写代码不要这么写。
效果一样。
强制类型转换。
1是40 2是4/8,3是10,4是4/8
逻辑与,左边为假右边就不计算了。
逻辑或,左边为真,右边就不计算了
逗号表达式是从左到右计算,整个表达式的结果是最后一个表达式的结果。
整型提升
一个char类型的占1个bit 相对于8个biye位,他要整型提升是因为 难以直接实现两个8比特字节直接相加运算(虽然机器指令
中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转
换为int或unsigned int,然后才能送入CPU去执行运算。
例如图中的a为5,b为126 先把a的原码写出来相加得出来后8位,首先看最高位是0或者1,是1补1,是0补0,得出来的是补码,因为整数在内存中的存储是补码形式的,然后-1取反得原码,因为打印的都是以原码形式打印的。
a与b会发生整形提升,a与b的值会发生变化。
无符号的数发生整形提升,高位补0
上面的这些大小都小于int类型
下面讨论大小大于或者等于int类型的整形提升
这些类型都是向上转换的。
数据存储
有符号数直接用int或者 signed int类型的
无符号直接用unsigned int 类型的
无符号不分最高位是正数还是负数,统一正数。
整形在内存中以补码形式存储
1+-1是通过补码形式实现+-的
原码取反+1得补码
补码取反+1得原码
把一个数的高位字节序内容放在低地址处,把一个低位字节序内容放在高地址处。这个叫大端存储
把一个数的高位字节序内容放在高地址处,把一个低位字节序内容放在地地址处 这个叫小端存储
放与拿相反。比如放进去的是44 33 22 11,拿出去的是11 22 33 44
vs里存的是小端存储模式
主要看起始地址,对起始地址解引用看是不是1还是0,并且还要强制类型转换成char*类型,int类型一次性访问4个字节。
由于c是无符号数,整形提升的时候最高位是1,由于是无符号数,前面直接补0,所以是255,正数的原码补码,反码一样。