位运算;很多的运算都是以字节作为最基本单位,但有些程序系统中也会要求在位(bit)一级进行运算或处理
& 按为与:只有两个二进制为1时结果才是1
| 按位或:只要对应的两个二进位有一个为1时,结果位就是为1.参与运算的两个数均以补码形式进行
^ 按位异或:只有对应的两个二进制为为相反的时候为1,即对应一个为0和对应的另个一为1时,结果才是1,否则都是为0
~ 取反:对参与运算的数进行按位取反,即把每一个位0的变成1,把1的变成0;
<< 左移:高位丢弃,低位补0;把所有的位进制数想左移
>> 右移:左边的运算数的个二进位全部右移若干位
对于有符号数,向右移动时,符号位的将随同移动。当为正数时,最高位补0,当为负数时,符号位为1。
例子1:
int main()
{
unsigned a, b;
printf("input a number\n");//例如:输入10时候
scanf_s("%d", &a);
b = a >> 5;
b = b & 15;
printf("a=%d\tb=%d\n", a, b);//a=10,b=0
return 0;
}
例子2:
int main()
{
char a = 'a',b= 'b';
int p, c, d;
p = a;
p = (p << 8) | b;
d = p & 0xff;
c = (p & 0xff00) >> 8;
printf("a=%d\nb=%d\nc=%d\nd=%d\n", a, b, c, d);
return 0;
}
位域:在信息存储时,并不需要占用一个完整的字节,而只需占几个或者一个二进制位。例如在存放一个开关量时,只有0和1两种状态
用以为二进制位就可以了,为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或者“位段”
位域:就是把一个字节中的二进位划分为几个不同区域,并说明每个区域的位数。每个域都有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示
1.位域的定义说明形式为:
struct 位域结构名{位域列表} 其中位域列表的形式为:类型说明符 位域名:位域长度
struct bs {
int a : 8;
int b : 2;
int c : 6;
}data;//说明data为bs变量,共占用两个字节。其中位域a占8位,位域b占2位,位域c占6位
对于位域的注意点:
1.一个位域必须存储在同一个字节中, 不能夸字节进行存储,如果一个字节的存储空间不够,则直接从下一个字节开始储存,
剩余不够的空间直接跳过不直接进行储存,也可以有意使某位域从下一单元开始。例如
struct bs
{
unsigned a : 4;
unsigned : 0;//当空域没有给予位域名的时候
unsigned b : 4;
unsigned c : 4;
};
2.由于位域不能跨过两个字节看,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进制
3.位域可以没有域名,这时它只用来做填充或调整位置。无名的位域是不能使用的。
struct k
{
int a : 1;
int : 2;
int b : 3;
int c : 2;
};//可以看出,位域在本质上就是一种结构类型,不过其成员是按二进制位分配的。
位域的使用和结构成员的使用是相同,其一般形式为:
位域变量名.位域名 位域允许各种格式输出。
int main()
{
struct bs {
unsigned a : 1;
unsigned b : 3;
unsigned c : 4;
}bit,*pbit;
bit.a = 1;
bit.b = 7;
bit.c = 15;
printf("%d,%d,%d\n", bit.a, bit.b, bit.c);
pbit = &bit;
pbit->a = 0;
pbit->b &= 3;
pbit->c |= 1;
printf("a=%d\tb=%d\tc=%d\n", pbit->a, pbit->b, pbit->c);
return 0;
}
数据结构题目:消失的数字,数组num包含从0到n的所有整数,但其中缺失了一个,请编写代码找出那一个缺失的整数。请优化在O(N)的时间复杂度之间完成。
//思路:num跟数组中数和[0,N]之间进行异或,结果就是要找的数
//原理:相同的两个数异或是0,而数组中没有6,[0,N]之间都有。。所以异或的结果就是缺失的6
//先思考几个小时,如果没有好思路再去看看别人的代码的思路,理解以后,后面不看他的再去实现。这样才能提高。
//OJ两种类型:1.IO型 (牛客上的居多);2.接口型 (leetcode居多)
int missingNumber(int* nums, int numsSize)
{
int x = 0;//为什么是0?因为0和任何数异或都是它本身
for (size_t i = 0; i < numsSize; ++i)
{
x ^= nums[i];//数组里面的值不是按顺序的,但是x和数组里面的值全部异或了一次,得到的x是一个异或出来的总值,所以但x再和一个顺序的数组
//进行异或时,每异或一次就会消掉一个值,那么等到最后一个剩下的就是缺失的值
}
for (size_t i = 0; i <= numsSize; ++i)//这里一定要是i<= numsSize.一定要多一个等于,因为我们是要出排查缺失的数组,所有一定是会多比原来缺失的数组多一个。
{
x ^= i;
}
return x;
}