一.位运算操作符
&、|、^、~、<<、>>
1.题——打印整数二进制的奇数位和偶数位
【题目内容】
获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列。
思路:
1. 提取所有的奇数位,如果该位是1,输出1,是0则输出0
2. 以同样的方式提取偶数位置
检测num中某一位是0还是1的方式:
1. 将num向右移动i位
2. 将移完位之后的结果与1按位与,如果:
结果是0,则第i个比特位是0
结果是非0,则第i个比特位是1
/*
思路:
1. 提取所有的奇数位,如果该位是1,输出1,是0则输出0
2. 以同样的方式提取偶数位置
检测num中某一位是0还是1的方式:
1. 将num向右移动i位
2. 将移完位之后的结果与1按位与,如果:
结果是0,则第i个比特位是0
结果是非0,则第i个比特位是1
*/
void Printbit(int num)
{
for(int i=31; i>=1; i-=2)
{
printf("%d ", (num>>i)&1);
}
printf("\n");
for(int i=30; i>=0; i-=2)
{
printf("%d ", (num>>i)&1);
}
printf("\n");
}
2.题——链接:二进制中1的个数__牛客网
题目详情:输入一个整数 n ,输出该数32位二进制表示中1的个数。其中负数用补码表示。
数据范围:−231<=n<=231−1- 2^{31} <= n <= 2^{31}-1−231<=n<=231−1
即范围为:−2147483648<=n<=2147483647-2147483648<= n <= 2147483647−2147483648<=n<=2147483647
示例1
输入 10
输出 2
说明:
十进制中10的32位二进制表示为0000 0000 0000 0000 0000 0000 0000 1010,其中有两个1。
#include <stdio.h>
int NumberOf1(int n) {
/* 通过位运算公式 n & (n - 1)可以消去二进制n的最右边的一个一(小伙伴们可以自己手动计算一下,负数正数都试试)。其上述代码的思想就是不断消1,消一次使得计数器加一。最后使n变成零结束循环。*/
int res = 0;
while(n!=0)
{
res++;
n=n&(n-1);
}
// for (int i = 0; i < 32; i++)
// {
// //res += (n >> i) & 1;
// }
return res;
}
int main() {
/*
题目:
输入一个整数 n ,输出该数32位二进制表示中1的个数。其中负数用补码表示。
思路:
通过不断向右移n然后和1按位与,得1则此时位置是1,否则是0
*/
int n = 0;
scanf("%d", &n); //输入n
printf("%d", NumberOf1(n));
return 0;
}
3.题——不使用临时变量交换两个数
int main()
{
int a = 0, b = 0;
scanf("%d %d", &a, &b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("%d %d", a, b);
return 0;
}
4.题——short*
下面代码的结果是:( )
#include <stdio.h>
int main()
{
int arr[] = {1,2,3,4,5};
short *p = (short*)arr;
int i = 0;
for(i=0; i<4; i++)
{
*(p+i) = 0;
}
for(i=0; i<5; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
【题目内容】
A. 1 2 3 4 5
B. 0 0 3 4 5
C. 0 0 0 0 5
D. 1 0 0 0 0
答案:B
解析:
arr数组在内存中的存储格式为:
0x00ECFBF4: 01 00 00 00
0x00ECFBF8: 02 00 00 00
0x00ECFBFC: 03 00 00 00
0x00ECFC00: 04 00 00 00
0x00ECFC04: 05 00 00 00
指针p的类型为short*类型的,因此p每次只能所有两个字节,for循环对数组中内容进行修改时,一次访问的是:
arr[0]的低两个字节,arr[0]的高两个字节,arr[1]的低两个字节,arr[1]的高两个字节,故改变之后,数组中内容如下:
0x00ECFBF4: 00 00 00 00
0x00ECFBF8: 00 00 00 00
0x00ECFBFC: 03 00 00 00
0x00ECFC00: 04 00 00 00
0x00ECFC04: 05 00 00 00
故最后打印:0 0 3 4 5
4.题——char*
【题目名称】
下面代码输出的结果是:( )
#include <stdio.h>
int main()
{
int a = 0x11223344;
char *pc = (char*)&a;
*pc = 0;
printf("%x\n", a);
return 0;
}
【题目内容】
A. 00223344
B. 0
C. 11223300
D. 112233
答案解析:
假设,a变量的地址为0x64,则a变量在内存中的模型为:
0x64| 44 |
0x65| 33 |
0x66| 22 |
0x67| 11 |
char*类型的指针变量pc指向只能指向字符类型的空间,如果是非char类型的空间,必须要将该空间的地址强转为char*类型。
char *pc = (char*)&a; pc实际指向的是整形变量a的空间,即pc的内容为0x64,即44,
*pc=0,即将44位置中内容改为0,修改完成之后,a中内容为:0x11223300
因此:选择C
5.题——sizeof()返回值
【题目名称】
下面代码的结果是:
#include <stdio.h>
int i;
int main()
{
i--;
if (i > sizeof(i))
{
printf(">\n");
}
else
{
printf("<\n");
}
return 0;
}
【题目内容】
A. >
B. <
C. 不输出
D. 程序有问题
答案解析:
C语言中,0为假,非0即为真。
全局变量,没有给初始值时,编译其会默认将其初始化为0。
i的初始值为0,i--结果-1,i为整形,sizeof(i)求i类型大小是4,按照此分析来看,结果应该选择B,但是sizeof的返回值类型实际为无符号整形,因此编译器会自动将左侧i自动转换为无符号整形的数据,-1对应的无符号整形是一个非常大的数字,超过4或者8,故实际应该选择A
这道题其实很隐蔽,真是虾仁猪心!!!
因此:选择A
5.题——语言中哪一种形式声明了一个指向char类型变量的指针p,p的值不可修改,但p指向的变量值可修改?( )
【题目内容】
A. const char *p
B. char const *p
C. char*const p
D. const char *const p
答案解析:
A:错误,const修饰*p,表示p指向的内容不能修改
B:错误,同上
C:正确,const修饰p本身,表示p的指向不能修改,p指向的空间中内容可以修改
D:错误,第一个const表示p指向的内容不能修改,第二个const表示p不能指向其他变量
因此,选择C