位运算
常见的位运算符:按位与&,按位或|,按位异或^,按位取反~,左移<<,右移>>
在移位中需要注意移位后的结果要在数据类型表示的范围内否则报错
负数的右移结果取决于编译器,补0或1
移动位数大于操作数的存储空间或是负数,移位结果没意义
#include <stdio.h>
void test_and();
void test_or();
void test_andor();
void test_fan();
int main(){
unsigned int a = 65535;
unsigned int b = 1;
test_and();
test_or();
test_andor();
test_fan();
return 0;
}
void test_and(){ //&按位与,两个操作数必须同位为1,才是1
int c;
c = 65535&1;
printf("%x\n",c);
}
void test_or(){ //|按位或,两个操作数一位为1,就为1
int c;
c = 15|241;
printf("%x\n",c);
}
void test_andor(){ //按位异或,两个操作数对应位不同时,才为1
int c;
c = 139^199;
printf("%x\n",c);
}
void test_fan(){ //按位取反,1变0,0变1
int c;
c = ~21845;
printf("%x\n",c);
}
位段
结构体或者共同体包含无符号整型或者有符号整形,c语言规定允许用户指定这些成员所占的存储位,这就是位域(位段)。
声明方式:
unsigned int a :3; //冒号后面是指定所占的位数
unsigned int : 4; //无名位段,这里面的值是不确定的
跨平台问题:
1.int位段被当成无符号数还是有符号数是不确定的
2.位段中的最大位的数目不能确定
3.位段中大小端未被定义
4.当一个结构体中包含两个位段,第二位段成员比较大,无法容纳第一个位段剩余的位时,是否舍弃还是利用不确定
补充
/*
讲一个整型变量向右移4位,以二进制形式输出位移前位移后的值,看是补0还是补1?
整数补0,负数补1
*/
#include <stdio.h>
void test(int a);
int main(){
int num;
printf("请输入一个数:\n");
scanf("%d",&num);
printf("%d\n",num);
test(num);
return 0;
}
void test(int a){
unsigned int mask=0x1<<31;
int t=a;
for(int i=1;i<=32;i++){
a&mask ? putchar('1') : putchar('0');
a=a<<1;
if(i%8==0){
printf(" ");
}
}
printf("\n");
t=t>>4;
for(int i=1;i<=32;i++){
t&mask ? putchar('1') : putchar('0');
t=t<<1;
if(i%8==0){
printf(" ");
}
}
}
输入正数:往后移四位,前面补0
输入负数,往后移四位,前面补1
/*
无符号数往左移相当于该数×2,编写函数,接受两个变量num和pow作为参数,被调用函数使用位移
运算计算num*2\^pow的结果,分别以整形和二进制形式输出
*/
#include <stdio.h>
int main(){
unsigned int num,pow;
printf("请输入一个无符号数:\n");
scanf("%u %u",&num,&pow);
printf("%u%u\n",num,pow);
test(num,pow);
return 0;
}
void test(unsigned int a,unsigned int b){
unsigned int mask = 0x1<<31;
printf("\n");
a=a<<1;
a=a^b ;
for(int i=1;i<=32;i++){
a&mask ? putchar('1') : putchar('0');
a=a<<1;
if(i%8==0){
printf(" ");
}
}
printf("\n");
}