首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >详解操作符

详解操作符

作者头像
用户11831438
发布2025-12-30 12:31:24
发布2025-12-30 12:31:24
1740
举报
1、操作符的分类

·算术操作符: + 、- 、* 、/ 、% •移位操作符: << >> •位操作符: & | ^ •赋值操作符: = 、+= 、 -= 、 *= 、 /= 、%= 、<<= 、>>= 、&= 、|= 、^= •单⽬操作符: !、++、--、&、*、+、-、~ 、sizeof、(类型) •关系操作符: > 、>= 、< 、<= 、 == 、 !=

•逻辑操作符: && 、|| •条件操作符: ? : •逗号表达式: , •下标引⽤: [] •函数调⽤: ()

•结构成员访问:. 、->

2、进制的转换

二进制:0,1 十进制:0,1,2,3,4,5,6,7,8,9

八进制:0,1,2,3,4,5,6,7 十六进制:0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f

众所周知,10进制是满10进1,其实二进制也是一样,2进制中满2进1

二进制转十进制

2进制的位

1

1

0

1

权重

2^3

2^2

2^1

2^0

权重值

8

4

2

1

求值

1*8=8

1*4=4

0*2=0

1*1=1

13

十进制转二进制

二进制转八进制

2^3=8,所以从2进制序列中从右往左数,每三个二进制位会换算一个八进制,剩余不够三位的直接换算

0

0

0

0

1

1

1

1

0

1

7

二进制转十六进制

2^4=8,所以从2进制序列中从右往左数,每4个二进制位会换算一个八进制,剩余不够4位的直接换算

3.原码、补码、反码

整数的2进制表示方法有三种方式,即原码、反码、补码

在有符号整数的二进制序列中,最高位的一位是被当作符号位,剩余的都是数值位。其中符号位一般都是用0表示“正数”,用1表示“负数”。

那不知道是否有些小伙伴会有疑惑?什么是有符号整数,什么又是无符号整数?

有符号整数就是在一个整数的前面有一个“+”(正号),或者有一个“-”(负号),而无符号整数就是该数前面没有符号(+或-)。

在上图的最高位1表示这个数是一个“负数”

在上图的最高位0表示这个数是一个“正数”。

正整数的原码、反码、补码都相同;负整数的三种表示方法各不相同。下面我们来看看负整数的三种表示方法该怎么表示。

原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码

反码:将原码的符号位不变,其他位(数值位)依次按位取反就可以得到反码

补码:反码+1就得到补码

补码-->原码:补码符号位不变,其余数值位按位取反后+1;

无符号整数的三种二进制的表示形式相同。

对于整型来说:数据存放内存中其实存放的是补码。这是因为在计算机系统中,数值⼀律⽤补码来表⽰和存储。原因在于,使⽤补码,可以将符号位和数值域统⼀处理;同时,加法和减法也可以统⼀处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

4.移位操作符

<< 左移操作符

>> 右移操作符(注意:移位操作符的操作数只能是整数,移动的是补码)

4.1 左移操作符

移位规则:左边抛弃,右边补0

代码语言:javascript
复制
int main()
{
	int n = 3;
	int num = n << 1;
	printf("num=%d\n", num);
	return 0;
}

左移操作符演示

在上图中,黄色的0表示丢弃的1位,红色的0表示补上的1位

4.2 右移操作符>>

规则:右移运算分为两种:

1、逻辑右移:左边用0填补,右边丢弃

2、算术右移:左边用符号位填补,右边丢弃

代码语言:javascript
复制
int main()
{
    int n = 3;
	int num =n>>1;
	printf("num=%d\n", num);
	return 0;
}

右移操作符演示

在大多数的编译器里面都是算术右移,也就是右边抛弃,左边用符号位填补,在上图中,红色的0表示的是填补上的符号位,红色的1表示被抛弃的。

警告:对于移位操作符,不要移动负数位

注意:移位移的是二进制位,也就是内存中的补码。

5.位操作符(二进制)

位操作符有:按位与 &、按位或 | 、按位异或 ^ 、按位取反 ~(操作数必须为整数)

5.1 按位与 &:

规则:比较两个数的补码上的每一位,全为1返回1,有0则返回0;

5.2 按位或 |

规则:比较两个数的补码上的每一位,全为0返回0,有1则返回1;

5.3 按位异或 ^

规则:对应的二进制补码相同为0,相异为1

注意:异或是支持交换律的

5.4 按位取反 ~

规则:按位取反(原来是0变为1,原来是1变为0)

写到这里,不知道有没有小伙伴感到疑惑?学了这么多操作符到底有什么用处呢?接下来我们来看看这些操作符该如何运用。

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

回顾之前所学的内容,我们知道如何进行创建第三变量实现两个整数的交换:

代码语言:javascript
复制
int main()
{
	int a = 10;
	int b = 20;
	int c = 0;
	c = a;
	a = b;
	b = c;
	printf("%d %d", a, b);
	return 0;
}

那如何不创建第三变量实现两个整数的交换呢?这就得用上上面所学的操作符啦!

根据上面所学的按位异或^操作符,相同为0,相异为1,我们可以得出a^a=0 a^0=a,如果我们现在创建两个变量a,b,是不是可以通过这个操作符实现交换?答案是肯定的

通过a^a=0,a^0=a,可以得出b=a^b^b,a=a^a^b,下面是代码实现:

代码语言:javascript
复制
int main()
{
	int a = 10;
	int b = 20;
	a = a ^ b;
	b = a ^ b;
	a = a ^ b;
	printf("%d %d", a, b);
	return 0;
}

如果有小伙伴对这个代码不是很理解,我们可以假设a1=a^b;b=a1^b;a=a1^b(此时这个表达式中的b是上一个表达式(b=a1^b)结果的b),在第二个表达式被执行的时候,b的值已经被a的值所替代,最终实现两个整数的交换。

编写代码实现:求一个整数存储在内存中的二进制中1的个数

一般情况下,我们脑海里想出来的解决方案是不是上面这种,但是如果我们仔细的想一想这种方法有没有啥问题?当我们输入-1的时候,这个代码会给我们返回0,真的对吗?答案当然是不对的。上面这种适合n为正整数时。

-1在内存中的存储是以补码的形式存储的,所以当我们输入-1的时候,应该要输出32,那我们该怎么改进这个代码呢?想一想,我们上面是不是学过很多操作符,那些操作符会不会有啥帮助呢?

下面是代码演示:

方法一:

代码语言:javascript
复制
int main()
{
	int n = 0;
	scanf("%d", &n);
	int count = 0;
	for (int i = 0; i < 32; i++)
	{
		if ((n >> i) & 1)
			count++;
	}
	printf("%d\n", count);
	return 0;
}
  1. 统计 1 的个数
    • 循环 32 次(对应 int 类型的 32 位二进制表示)。
    • (n >> i) & 1
      • n 右移 i 位,获取第 i 位的值。
      • 通过 & 1 操作检查该位是否为 1
    • 若为 1,则计数器 count1

方法2:

代码语言:javascript
复制
int main()
{
	int n = 0;
	int count = 0;
	scanf("%d", &n);
	while (n)
	{
		n = n & (n - 1);
		count++;
	}
	printf("%d\n", count);
	return 0;
}

二进制中有几个1就循环几次。

  • 核心算法:n = n & (n - 1) 每次消除 n 的二进制中最右侧的 1,直到 n 变为 0

判断一个数是否是2的次方数?

4 =2^2 00100 8=2^3 01000 可以看出一个数如果是2的次方数,那么补码中只有一个1。

代码语言:javascript
复制
int main()
{
	int n = 0;
	scanf("%d", &n);
	if ((n & (n - 1)) == 0)
		printf("true\n");
	return 0;
}

练习2:⼆进制位置0或者置1 编写代码将13⼆进制序列的第5位修改为1,然后再改回0(其余位不变)

代码语言:javascript
复制
int main()
{
	int n = 13;
	n = n | (1 << (5-1));
	printf("%d\n", n);
	//00000000000000000000000000001101 
	//00000000000000000000000000010000  5<<1
	//00000000000000000000000000011101  13|(5<<1)
	n = n & (~(1 << (5-1)));
	printf("%d\n", n);
	//11111111111111111111111111101111   ~(5<<1)
	//00000000000000000000000000001101  13|(5<<1)&(~(5<<1))
	return 0;
}
6.逗号表达式

exp1,exp2,exp3,exp4……expn

逗号表达式,从左向右依次执行,整个表达式的结果是最后一个表达式的结果。

7.整型提升

C语言中整型算术运算总是以默认整型类型的精度来进行的,为了获得这个精度,表达式中的字符(char)和短整型(short int)在使用之前要被转换成普通整型。

表示中的各种长度可能小于int长度的整型值,都必须先转换为int 或unsigned int ,才能进行运算。

如何进行整型提升?

1、有符号整数提升是按照变量的数据类型的符号位来提升(最高位作为符号位)

2、无符号整数提升,高位补0。

代码语言:javascript
复制
int main()
{
	char a = 20;
	char b = 120;
	char c = a + b;
	printf("%d\n", c);
	return 0;
}
8.算术转换

如果某个操作符的各个操作数属于不同的

类型,那么除非其中一个操作数转换为另一个操作数的类型,否则操作就无法进行。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-06-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、操作符的分类
  • 2、进制的转换
  • 3.原码、补码、反码
  • 4.移位操作符
    • 4.1 左移操作符
    • 4.2 右移操作符>>
  • 5.位操作符(二进制)
    • 5.1 按位与 &:
    • 5.2 按位或 |
    • 5.3 按位异或 ^
    • 5.4 按位取反 ~
  • 6.逗号表达式
  • 7.整型提升
  • 8.算术转换
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档