- 魔王的介绍:😶🌫️一名双非本科大一小白。
- 魔王的目标:🤯努力赶上周围卷王的脚步。
- 魔王的主页:🔥🔥🔥大魔王.🔥🔥🔥
❤️🔥大魔王与你分享:“没什么好难过的,只是错把路灯当成了月亮”。
文章目录
- 一、内存存储
- 1、位段的理解
- 2、大小端、联合
- 二、操作符
- 1、按位操作符
- 2、按位操作符
- 3、按位异或(^),移位操作符
- 知识点:
- 思路:
- 代码实现:
- 三、总结
一、内存存储
1、位段的理解
题目:求运行结果
求运行结果()
分析:创建的puc数组为4个char类型成员,结构体指针pstPimDate指向这个puc这个数组(强转的形式把首元素指针puc赋给结构体指针pstPimDate,那么之后看待的角度是根据这个结构体指针的角度来看待的)。
第一个成员大小为一字节也就是8bit,第二个成员只分配了1bit,第三个分配了2bit,第四个分配了3bit。
接下来进行赋值,如图:
正数原反补相同,所以原码就是补码。。
不同编译器结果可能不一样,因为位段占用的bit空间不确定是从每个字节的开头往高地址用还是每个字节的结尾往小地址用。
所以结果为:02 29 00 00
2、大小端、联合
题目:按照小端字节序存储,问输出的结果
小端即小端字节序存储,存放的规律为:低位在低地址,高位放在高地址。
i[0]为低位,放的是39,i[1]为高位,放的是38。 即内存中:39(低位) 38(高位)
当内存读取时,会按照小端的特点进行读取,也就是将低位的数当做小数,将高位的数当作大树,所以按照十六进制输出的结果是 38 39
二、操作符
1、按位操作符
题目:统计二进制中1的个数
思路:
采用遍历法,每次判断一位。判断后让1左移一位继续判断,直到32位判断完。
代码如下:
#include <stdio.h>
int count(int a)
{
int n = 0;
for (int i = 0; i < 32; i++)
{
if ((a & (1 << i)) != 0)
n++;
}
return n;
}
int main()
{
int a = 0;
scanf("%d", &a);
int num = count(a);
printf("%d\n", num);
return 0;
}
2、按位操作符
题目:打印整数二进制的奇数位和偶数位。
思路:
奇数就从1开始每次左移两个,偶数就从0开始每次左移两个。
代码实现:
#include <stdio.h>
void print(int a)
{
int i = 0;
printf("打印奇数二进制位:");
while (i < 32)
{
if ((a & (1 << i)) == 0)
{
printf("0");
}
else
printf("1");
i += 2;
}
printf("\n打印偶数二进制位:");
i = 1;
while (i < 32)
{
if ((a & (1 << i)) == 0)
{
printf("0");
}
else
printf("1");
i += 2;
}
}
int main()
{
int a = 0;
scanf("%d", &a);
print(a);
return 0;
}
3、按位异或(^),移位操作符
题目:找单身狗:一个数组中只有两个数字是出现一次,其他所有数字都出现了两次,编写一个函数找出这两个只出现一次的数字。
知识点:
右移操作符>> :二进制序列向右移一位,逻辑移位左边补0,算数移位左边补原来的。
左移操作符>> :二进制序列向左移一位,右边补0
按位与& :有0为0,两个为1才为1
按位异或^ :相同为0,不同为1.
思路:
首先将数组里的数都按位异或一遍,那么结果就是两个单身狗的值。
在这个值的二进制序列里任意找一位为1的(说明它们这里不一样),以此为界,分成两个数组,用按位与(&)来实现让这个位置的二进制序列为1的去一个数组里,不为1的去另一个数组。
这样两个不相等的书就会存放在不一个数组中。
让这两个数组分别按位异或,最后的值就是单身狗的值。
代码实现:
//找单身狗
#include <stdio.h>
#include <stdlib.h>
void FindDog(int* arr1, int sz)
{
int sum = 0;
int tep = 0;
int* arr2 = NULL;
int* arr3 = NULL;
arr2 = calloc(sz,sizeof(int));
if (arr2 == NULL)
{
return;
}
arr3 = calloc(sz, sizeof(int));
if (arr3 == NULL)
{
return;
}
for (int i = 0; i < sz; i++)
{
sum ^= arr1[i];
}//先找出数组中两个单身狗按位异或的值。
for (int i = 0; i < 32;i++)
{
if ((sum & (1<<i)) != 0)//跟0比,如果!=0,说明二进制中第i位不是0
{
tep = i;
break;
}
}//找出两个单身狗按位异或的值的二进制位中不一样的一项,以这一项为分界,分为两部分,那么这两个数会位于不同的部分。
for (int i = 0; i < sz; i++)
{
if ((arr1[i] & (1 << tep)) == 0)//分组,二进制中第i位是0的放一起,不是的放一起
{
arr2[i] = arr1[i];
}
else
{
arr3[i] = arr1[i];
}
}
int m = 0;
for (int i = 0; i < sz; i++)
{
m ^= arr2[i];//寻找两个单身狗按位异或后的二进制序列里不相同的一项。
}
printf("%d\n", m);//打印本数组中的单身狗
int n = 0;
for (int i = 0; i < sz; i++)
{
n ^= arr3[i];
}
printf("%d\n", n);//打印本数组中的单身狗
}
int main()
{
int arr[] = {1,1,2,2,4,6};
FindDog(arr, sizeof(arr)/sizeof(arr[0]));
return 0;
}
if ((sum & (1<<i)) != 0)这个式子sum&(1<<i)要再加一层括号是因为优先级。
三、总结
✨✨请点击下面关注大魔王✨✨
❤️🔥❤️🔥❤️🔥❤️🔥❤️🔥❤️🔥❤️🔥❤️🔥大魔王.❤️🔥❤️🔥❤️🔥❤️🔥❤️🔥❤️🔥❤️🔥❤️🔥