操作符的基本语法(一)

1.操作符的分类

  • 算术操作符: + 、- 、* 、/ 、%
  • 移位操作符:<< 、>>
  • 位操作符:&、 |、 ^
  • 赋值操作符:= 、+= 、 -= 、 *= 、 /= 、%= 、<<= 、>>= 、&= 、|= 、^=
  • 单目操作符:!、++、–、&、*、+、-、~ 、sizeof、(类型)
  • 关系操作符:> 、>= 、< 、<= 、 == 、 !=
  • 逻辑操作符: && 、||
  • 条件操作符: ? :
  • 逗号操作符:
  • 下标引用:[ ]
  • 函数调用:()
  • 结构成员访问:. 、->

今天介绍一些与二进制有关的操作符,先了解一下二进制和进制转换的知识

2. 二进制和进制的转换

其实我们经常能听到 2进制、8进制、10进制、16进制 这样的讲法,那是什么意思呢?其实 2进制、8进制、10进制、16进制 是数值的不同表示形式而已。
比如:数值15的各种进制的表示形式:

152进制:1111
158进制:17
1510进制:15
1516进制:F

//16进制的数值之前写:0x
//8进制的数值之前写:0

重点介绍一下二进制:
首先我们还是得从10进制讲起,其实10进制是我们生活中经常使用的,我们已经形成了很多尝试:

10进制中满10进1
10进制的数字每一位都是0~9的数字组成

其实二进制也是一样的

2进制中满2进1
2进制的数字每一位都是0~1的数字组成

那么 1101 就是二进制的数字了。

2.1 2进制转10进制

其实10进制的123表示的值是一百二十三,为什么是这个值呢?其实10进制每一位是有权重的10进制的数字从右向左是个位、十位、百位…,分别每⼀位的权重是 10^0 , 10^1 , 10^2 …

如下图:
10进制123每一位权重的理解
在这里插入图片描述
2进制与10进制是类似的,只不过2进制的每一位的权重,从右往左是:2^0, 2^1, 2^2 ……

如果是2进制的1101,该怎么理解?
在这里插入图片描述

2.1.1 10进制转2进制数字

在这里插入图片描述

2.2 2进制转8进制和16进制

2.2.1 2进制转8进制

8进制的数字每一位是 0~7 的,0~7 的数字,各自写成 2 进制,最多有 3 个 2 进制位(2^3 = 8)就足够了,比如 7 的二进制是 111,所以在 2进制转 8 进制数的时候,从 2进制序列中右边低位开始向左每3个2进制位会换算一个8进制位,剩余不够 3 个 2进制位的直接换算。

如:2进制的 01101011 ,换成8进制:0153,8进制表示的时候前面加 0
在这里插入图片描述

2.2.2 2进制转16进制

16进制的数字每一位是 0~9 , a ~f 的,0~9,a ~f 的数字,各自写成2进制,最多有4个2 (2^4 = 16)进制位就足够了,比如 f 的二进制是1111,所以在2进制转16进制数的时候,从2进制序列中右边低位开始向左每4个2进制位会换算一个16进制位, 剩余不够4个二进制位的直接换算。

如:2进制的 01101011 ,换成8进制:0x6b,8进制表示的时候前面加 0x
在这里插入图片描述

3.原码、反码、补码

整数的2进制表示方法有三种,即原码、反码、补码
有符号整数的三种表示方法均有符号位数值位,2进制序列中,最高位的1位是被当成符号位的,剩余的都是数值位
符号位都是用0表示“正”,用1表示“负”
正整数的原、反、补码都相同。
负整数的三种表示形式各不相同。

原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码。
反码:将原码的符号位不变其他位依次按位取反就可以得到反码。
补码反码+1就得到补码。

补码得到原码也是可以使用:取反,+1的操作。
对于整型来说:数据存放内存中其实存放的是补码。
为什么?

在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

4.移位操作符

<< 左移操作符
>> 右移操作符
注:移位操作符的操作数只能是整数

4.1左移操作符

左移规则:左边丢弃,右边补零

#include<stdio.h>

int main()
{
	int num = 10;
	int n = num << 1;

	printf("n = %d\n", n);
	printf("num = %d\n", num);

	return 0;
}

在这里插入图片描述

4.1右移操作符

右移规则:先右移,运算分两种:

逻辑右移:左边用0补充,右边丢弃
算术右移:左边用原该值的符号为补充(在VS2022使用算术右移的)

#include<stdio.h>

int main()
{
	int num = 10;
	int n = num >> 1;

	printf("n = %d\n", n);
	printf("num = %d\n", num);

	return 0;
}

逻辑右移1位演示:

在这里插入图片描述

算术右移1位演示:
在这里插入图片描述

警告:对于移动运算符,不要移动负数位,这个是标准未定义的。

int num = 10;
num >> -1;//error

5.位操作符:&、|、^、~

位操作符有:

&    //按位与
|    //按位或
^    //按位异或
~    //按位取反

注:他们的操作数必须是整数。

看一段代码:

#include<stdio.h>

int main()
{
	int num1 = -1;
	int num2 = 3;

	printf("%d\n", num1 & num2);//3
	printf("%d\n", num1 | num2);//-1
	printf("%d\n", num1 ^ num2);//4
	printf("%d\n", ~0);//-1

	return 0;
}

题目:
不能创建临时变量(第三个变量),实现两个整数的交换。

#include<stdio.h>

int main()
{
	int a = 10;
	int b = 20;
	//打印前:
	printf("打印前:a = %d b = %d\n", a, b);
	a = a ^ b;
	b = a ^ b;//a ^ b ^ b = a ^ 1 = a;
	a = a ^ b;//a ^ a ^ b = 1 ^ b = b;
	//打印后:
	printf("打印后:a = %d b = %d\n", a, b);

	return 0;
}

练习1:编写代码实现:求一个整数存储在内存中的二进制(补码)中1的个数。

//方法1:
#include<stdio.h>

int main()
{
	int num = 10;//1010
	int count = 0;//计数

	while (num)
	{
		if (num % 2 == 1)
		{
			count++;
		}
		num = num / 2;
	}

	printf("二进制中1的个数 = %d\n", count);

	return 0;
}

//思考这样的实现方式有没有问题?
//这种方法只能算无符号的数据,具有局限性

//方法2:
#include<stdio.h>

int main()
{
	int num = -1;//int 类型是 4byte = 32bit
	int i = 0;
	int count = 0;//计数

	for (i = 0; i < 32; i++)
	{
		if (num & (1 << i))
		{
			count++;
		}
	}
	//打印
	printf("二进制中1的个数 = %d\n", count);

	return 0;
}

//这里必须循环32次的,能不能再优化。

//方法3:
#include<stdio.h>

int main()
{
	int num = -1;
	int i = 0;
	int count = 0;//计数

	while (num)
	{
		count++;
		num = num & (num - 1);//直接把二进制的1算出来
	}

	printf("二进制中1的个数 = %d\n", count);

	return 0;
}

//这种方式是不是很好?达到了优化的效果,但难以想到

练习2:二进制位置0或者置1

编写代码将13 二进制序列的第5位修改为1,然后再改回0

132进制序列: 00000000000000000000000000001101
将第5位置为1后:00000000000000000000000000011101
将第5位再置为000000000000000000000000000001101

代码如下:

#include<stdio.h>

int main()
{
	int a = 13;

	a = a | (1 << 4);
	printf("将第5位置为1后:a = %d\n", a);//29
	//
	a = a & ~(1 << 4);
	printf("将第5位再置为0:a = %d\n", a);//13

	return 0;
}

6.单目操作符

单目操作符有这些:

!、++--&*+-~sizeof(类型)
  • 22
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值