C语言:位运算、移位运算、类型转换详解、多种位运算实例分析

一、位运算符

1.1按位取反

按位取反~:作用是按位将0变成1,1变成0;

如:二进制10011010取反后
~(10011010)——> 01100101//原码

实例1: 先按位取反,但是在计算机中存储需要将原码按照补码方式存储,因此符号位不变再取反+1。

void test()
{
	int num = 2;
	//0000 0010 —>1111 1101原码 
	//—>取反1000 0010 加1—>1000 0011 —>-3
	printf("%d\n",~num);
}

输出结果为:
在这里插入图片描述
实例2: 此时我们需要了解各种类型数据的取值范围。unsigned char的取值范围为:0—255,我们看如下例子。
在这里插入图片描述

void test()
{
	unsigned char a = 2;//0000 0010
	unsigned char b = ~a;//-3,但为无符号char类型,1000 0011—>
	//1111 1100(负数转换变为正数)—>(正数)1111 1101—>253
	printf("a = %d\n",a);//2
	printf("b = %d\n",b);
}

输出结果:a为正数不变;b与上面一样2的补码为-3,但此时为unsigned char类型数据需要进行再次转换,计算机中的负数以二进制补码表示,补码 = 二进制数(原码)的反码 + 1。
在这里插入图片描述
 

1.2按位与

按位与&:作用是按位与,全真为真(1),有一个假即为假(0);

如:二进制数10001101按位与后
          10101010——>10001000

实例1: 判断任意一个数字的奇偶性。任意一个数字与上1,结果为1,是奇数;为0,是偶数;

随意写一个数字10010101与上1
            00000001
            00000001//结果为1,是奇数;为0,是偶数;

简单测试一下:

void test()
{
	int num = 123;
	if ((num&1) == 0)//与上1
	{
		printf("num为偶数\n");
	}
	else
	{
		printf("num为奇数\n");
	}
}

测试成功:
在这里插入图片描述
 

1.3按位或

按位或 |:作用是作用是按位或,全真为真(1),有一个真(1)也为真,全假才为假(0);

如:二进制数10010100按位或后
          01110010——>11110110

实例1: 按位或操作

void test()
{
	int num1 = 5;
	int num2 = 3;
	printf("num1|num2 = %d\n",num1|num2);//0101
	                                     //0011—>0111—>7
}

测试结果:为7
在这里插入图片描述
 

1.4按位异或

按位异或^:作用是按位异或:两个不一样为真,输出1;两个一样,为假,输出0;

按位异或:相同为0,不同为110010101 进行按位异或
                        00011100——>10001001

在这里插入图片描述
实例1:实现两个数交换的多种方法
方式1:使用临时变量方法即可完成交换

	int temp = num1;
	num1 = num2;
	num2 = temp;

方式2:利用按位异或实现两个数的交换(不使用临时变量交换的方法)

void test()//利用按位异或实现两个数的交换
{
	int num1 = 10;
	int num2 = 20;
	printf("交换前:\n",num1);
	printf("num1 = %d\n",num1);
	printf("num2 = %d\n",num2);

	num1 = num1^num2;
	num2 = num1^num2;
	num1 = num1^num2;
	printf("交换后:\n",num1);
	printf("num1 = %d\n",num1);
	printf("num2 = %d\n",num2);
}

方式3:我们将其中这三行修改也可以实现2个数交换,输出结果是相同的。

    num1 = num1 + num2;
	num2 = num1 - num2;
	num1 = num1 - num2;

最后测试结果都测试成功。
在这里插入图片描述

二、移位运算符

2.1左移运算符

左移运算符<<:将其操作数的值的每位向左移动,移动的位数由其右侧操作数指定。空出来的位用0填充,并且丢弃移出左侧操作数末端的位。左移X次代表乘以2^X次方。
在这里插入图片描述
实例1:左移X次代表乘以2^X次方。

void test()//左移运算符
{
	int num = 10;
	printf("num = %d\n",num<<2);//相当于乘4
}

输出结果:
在这里插入图片描述

2.2右移运算符

右移运算符>>:将其左侧的操作数的值每位向右移动,移动的位数由其右侧的操作数指定。丢弃移出左侧操作数有段的位。左移X次代表除以2^X次方。 对于unsigned类型,使用0填充左端空出的位。对于有符号类型,结果依赖于机器,空出来的位可能用0填充,或者使用符号(最左端)位的副本填充。不同的机器可能有不同的结果。 正数则左边补0,负数标准没有规定在左边补充的数字,分为逻辑右移和算术右移,具体由编译器决定。windows平台和gcc采取算术右移即负数补1。
在这里插入图片描述
实例1:右移X次代表除以2^X次方。

void test()//右移运算符
{
	int num = 10;
	printf("num = %d\n",num>>1);//相当于除2
}

输出结果:
在这里插入图片描述
 

三、类型转换详解

类型转换: 当参加一个运算的数据的类型不同时运算需要类型转换。首先变量的数据类型是可以转换的。转换的方法有两种,一种是显示转换,另一种是隐式转换。
显示转换:

char a = (char)200;//显示转换,-56   -(256-200)
int b = (int)12.5;//显示转换 12

隐式转换:

char c = 100;
int d = c + 25;//隐式转换,自动转换为整型

我们还需要了解一下各种类型数据范围,为什么呢?
       类型转换时,就像我们把1个字节东西放入4个字节的盒子时,是没有问题的;但是,如果把4个字节东西放入1个字节盒子里时,放不下去自然要进行相应转化才能放进去。因此,我们就要了解一下各种数据类型范围:

转换规则:
在这里插入图片描述
各种数据类型范围:
在这里插入图片描述
案例1:类型转换1。

void test()
{
	char a = -1;//-1
	char b = 255;//-1
	unsigned char c = a;//255
	unsigned char d = b;//255
	int e = a;//-1
	int f = b;//-1
	unsigned int g = a;//2^32-1
	unsigned int h = b;//2^32-1
	printf("%d %d %d %d\n",a,b,c,d);
	printf("%d %d %u %u\n",e,f,g,h);
}

输出结果为:如下
①char类型的范围为-127~128,所以a还是-1,但是b自动转换为255了。
②unsigned char类型范围为:0-255,所以c,d都为255;
③int类型范围为-几亿~+几亿,范围足够大,所以e,f还是-1;
④unsigned int范围为0~4294967295,因此需要将-1转换为4296967295。
在这里插入图片描述
案例2:类型转换2。

void test()
{
	unsigned short a = 10;
	unsigned int b = 10;

	if (a > -1)//a提升为整型10
	{
		printf("a>-1\n");
	}
	else
	{
		printf("a<-1\n");
	}

	if (b > -1)
	{
		printf("b>-1\n");
	}
	else
	{
		printf("b<-1\n");
	}
}

输出结果为:
在这里插入图片描述
为什么呢?
a为unsigned short类型,-1为整型,整型类型大,因此直接将a提升为整型的10;因此10>-1;
b为unsigned int类型,-1为整型,同级别:无符号整型>整型;-1转化为无符号整型大约为40多亿,大于10,因此b<-1;

窄的符号类型如何变成宽的符号类型呢?
窄变宽:左边补符号位(无符号数左边补0)。
在这里插入图片描述
案例2:类型转换3。

void test()
{
	int d = 200;
	char b = 200;
	b = (char)d;//-56
	d = (int)b;//-56
	printf("%d\n",d);
}

输出结果:b为char类型,存储不下200,需要转换为-56;
d为int类型,可以存储-56,最后输出-56;
在这里插入图片描述
 

四、多种位运算实例分析

综合实例1: 常见的二进制位的变换操作:定符号、定数字、构造数字。
在这里插入图片描述
综合实例2:(10<<8)|2
在这里插入图片描述
我们用代码验证一下:

void test()
{
	int num = 10;
	printf("num = %d\n",num<<8|2);
}

输出结果为:
在这里插入图片描述

  • 20
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值