C语言:操作符详解

news2024/12/26 9:25:18

往期文章

  1. C语言:初识C语言
  2. C语言:分支语句和循环语句
  3. C语言:函数
  4. C语言:数组

目录

  • 往期文章
  • 前言
  • 1. 操作符分类
  • 2. 算术操作符
  • 3. 移位操作符
  • 4. 位操作符
  • 5. 赋值操作符
  • 6. 符合赋值符
  • 7. 单目操作符
  • 8. 关系操作符
  • 9. 逻辑操作符
  • 10. 条件操作符
  • 11. 逗号表达式
  • 12. 下标引用、函数调用和结构成员
  • 13. 表达式求值
    • 13.1 隐式类型转换
    • 13.2 算术转换
    • 13.3 操作符的属性
  • 后记

前言

继续更文,坚持就是胜利,开学就考试,已经愁死了。兄弟们记住,那些开学就考试的学校脑瓜子绝对不正常,一定要远离。
今天我们来更新操作符相关知识,放心,一定干货满满,欢迎阅读点赞收藏哦。之前有一篇关于操作符的拙作,欢迎大家点击查看:操作符详解

在这里插入图片描述

1. 操作符分类

在这里插入图片描述

2. 算术操作符

在这里插入图片描述

  1. 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。
  2. 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
  3. % 操作符的两个操作数必须为整数。返回的是整除之后的余数。

3. 移位操作符

学习移位操作数之前我们先了解一下关于二进制的知识:
整数的二进制有三种表示形式,原码、反码、补码。
正数的原码、反码、补码是相同的,负数的反码和补码需要经过一定的运算,最高位为符号位,原码符号位不变,其他按位取反为反码,反码的基础上加1为补码。整数在内存中是通过补码的形式存储的。

在这里插入图片描述
在这里插入图片描述
我们左移操作符实际是移动存储在内存中的二进制补码。

在这里插入图片描述
于是移动之后的二进制数字为1010,换成10进制是10.我们可以发现左移一位的本质是乘以2.
在这里插入图片描述
在这里插入图片描述
右移分为算术右移和逻辑右移,具体是哪种移位方式,需要看具体机器。用正数是看不出机器采用哪种移位的:
在这里插入图片描述
我们用负数来测试一下博主目前的机器是哪种移位方式。

#include<stdio.h>

int main()
{
	int a = -1;
	int b = a >> 1;
	printf("%d\n", b);
	return 0;
}

在这里插入图片描述

在这里插入图片描述
可知在博主的机器上是算术右移。

注意:对于移位运算符,不要移动负数位,这个是标准未定义的。不要乱操作,不一定会搞出什么乱七八糟的东西。

在这里插入图片描述

4. 位操作符

在这里插入图片描述
按位与是两位数都为1时结果才为1。
按位或是两位数有一个为1结果就为1.
按位异或是两位数不同时结果才为1.

#include <stdio.h>
int main()
{
	int num1 = 3;
	int num2 = 5;
	int a= num1 & num2;
	int b= num1 | num2;
	int c= num1 ^ num2;
	printf("%d	%d	%d\n", a, b, c);
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
注意,这三个操作符只能作用于整形哦。
我们来看一下操作符的应用,看这样一道题,如何在不创建第三个变量的情况下,实现两个数字的交换。一种代码实现方式如下:

#include <stdio.h>
int main()
{
	int a = 3;
	int b = 5;
	a = a^b;
	b = a^b;
	a = a^b;
	printf("a = %d b = %d\n", a, b);
	return 0;
}

在这里插入图片描述
在这里插入图片描述
感受到位运算的神奇啦吗?如果考试遇到两个数的交换问题,这不秀老师一脸。
在这里插入图片描述

我们再来看一个题目:求一个整数存储在内存中的二进制中1的个数。
最简单我们能想到的一种方法是:

#include <stdio.h>
int main()
{
	int num = 10;
	int count = 0;//计数
	while (num)
	{
		if (num % 2 == 1)
			count++;
		num = num / 2;
	}
	printf("二进制中1的个数 = %d\n", count);
	return 0;
}


在这里插入图片描述
我们知道十进制数字转换为二进制我们通常用短除法,这种计算方法就是短除法的模拟来计算几个1.
除此之外,我们能不能用位操作来实现这道题目呢?我们想一下,如果我们给一个二进制数字按位与上一个1,会得到什么样子的结果呢?

在这里插入图片描述

在这里插入图片描述
我们可以发现,如果一个二进制数字末尾为0,按位与1后结果为0,如果末尾为1,按位与1后结果为1.

根据这个原理,我们可以有这样的代码:

#include <stdio.h>
int main()
{
	int num = -1;
	int i = 0;
	int count = 0;//计数
	for (i = 0; i<32; i++)
	{
		if (((num >> i) & 1) == 1)
			count++;
	}
	printf("二进制中1的个数 = %d\n", count);
	return 0;
}

在这份代码的基础上,我们发现必须要循环32次,把每一位都检验,于是,我们还可以继续优化如下,避免循环32次会出现的浪费情况,这种实现方法十分精妙:

#include <stdio.h>
int main()
{
int num = -1;
int i = 0;
int count = 0;//计数
while(num)
{
count++;
num = num&(num-1);
}
printf("二进制中1的个数 = %d\n",count);
return 0;
}

5. 赋值操作符

赋值操作符是“=”,可以连续赋值,但是为了代码的易读性还是尽量不用。赋值操作符很简单,不多哔哔,进入下一节。

6. 符合赋值符

在这里插入图片描述
复合赋值不过是将代码写地更简单一些。我们举一个例子:

int x = 10;
x = x+10;
x += 10;//复合赋值

两个表达式意义一致。

7. 单目操作符

在这里插入图片描述
逻辑反!作用为真变假,假变真。
负值、正值操作符我们就不讲啦。
sizeof是用来计算所占字节大小的,sizeof是操作符而非函数。在某些情况下,后面的括号是可以省略的。sizeof内部的表达式是不计算的。

#include<stdio.h>

int main()
{
	short s = 3;
	int a = 10;
	printf("%d\n", sizeof(s = a + 5));
	printf("%d\n",s);
	return 0;
}

在这里插入图片描述
我们发现这段代码出来的结果是2和3,a是int,加上5之后为15也是int型,但是将范围大的量赋值给范围小的量会转换为范围小的量,所以最后的结果仍然是short,这里涉及到类型转换的知识。而括号内的表达式不计算,这则涉及到编译链接的知识。
在这里插入图片描述

~对一个二进制数按位取反。1变0,0变1.

#include<stdio.h>

int main()
{
	int a = 0;
	//00000000000000000000000000000000补码
	//11111111111111111111111111111111补码
	//打印出的值是原码对应的值,所以要减一然后除符号位取反
	//11111111111111111111111111111110
	//10000000000000000000000000000001
	printf("%d\n", ~a);
	return 0;
}

在这里插入图片描述

我们要重点讲述一下++和–,因为前置和后置经常把我们绕懵逼。

//前置++和--:
#include <stdio.h>
int main()
{
	int a = 10;
	int x = ++a;
	//先对a进行自增,然后对使用a,也就是表达式的值是a自增之后的值。x为11。
	int y = --a;
	//先对a进行自减,然后对使用a,也就是表达式的值是a自减之后的值。y为10;
	return 0;
}
//后置++和--
#include <stdio.h>
int main()
{
	int a = 10;
	int x = a++;
	//先对a先使用,再增加,这样x的值是10;之后a变成11;
	int y = a--;
	//先对a先使用,再自减,这样y的值是11;之后a变成10;
	return 0;
}



一定要注意前置后置的区别,考试别被绕进去。
在这里插入图片描述
强制类型转换括号里面放类型。

8. 关系操作符

在这里插入图片描述
比较简单,在编程的过程中== 和=不小心写错,导致错误,一定要注意。

9. 逻辑操作符

在这里插入图片描述
逻辑与都真为真,逻辑或一假为假。
我们来看一道题目:

#include <stdio.h>

int main()
{
	int i = 0, a = 0, b = 2, c = 3, d = 4;
	i = a++ && ++b && d++;
	//i = a++||++b||d++;
	printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);
	printf("%d\n", i);
	return 0;
}
//程序输出的结果是什么?

在这里插入图片描述
原因如下:
在这里插入图片描述
对于逻辑与操作符,左边证明为假,右边不再计算。
当我们把逻辑与换为逻辑或,我们a的初始值置为1:

#include <stdio.h>

int main()
{
	int i = 0, a = 1, b = 2, c = 3, d = 4;
	//i = a++ && ++b && d++;
	i = a++||++b||d++;
	printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);
	printf("%d\n", i);
	return 0;
}
//程序输出的结果是什么?

在这里插入图片描述

在这里插入图片描述
逻辑或左边操作数证明为真,右边不计算了。

10. 条件操作符

在这里插入图片描述
也叫三目操作符,是C语言中唯一一个三目操作符。
表达式1为真,整个表达式为表达式2的结果,否则为表达式3的结果。
在这里插入图片描述

11. 逗号表达式

在这里插入图片描述
逗号表达式,就是用逗号隔开的多个表达式。 逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。

#include<stdio.h>

int main()
{
	int a = 1;
	int b = 2;
	int c = (a>b, a = b + 10, a, b = a + 1);
	printf("%d\n", c);
	return 0;
}

在这里插入图片描述

12. 下标引用、函数调用和结构成员

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

13. 表达式求值

以上操作符我们就已经介绍完了,但是在实际运用中,还需要大家多多注意每一种操作符的用法。
表达式求值的顺序一部分是由操作符的优先级和结合性决定。
同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。
所以接下来,我们来具体看看表达式的求值。

13.1 隐式类型转换

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

我们通过一个例子来看整型提升的过程:

#include<stdio.h>

int main()
{
	char a = 3;
	char b = 127;
	char c = a + b;
	printf("%d\n", c);
	return 0;
}

在这里插入图片描述

13.2 算术转换

如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。下面的层次体系称为寻常算术转换。
如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。
在这里插入图片描述

13.3 操作符的属性

在这里插入图片描述
在这里插入图片描述
注意:我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题的。

比如这个表达式:ab + cd + ef
在计算的时候,由于比+的优先级高,只能保证,的计算是比+早,但是优先级并不能决定第三个
比第一个+早执行。
在这里插入图片描述
所以这样的代码其实是存在问题的。

后记

好的,这次文章就先分享到这里了,很用心的博客,期待大家的支持。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/193052.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java 中的基本设计模式

设计模式是针对常见软件设计问题的可重用解决方案。它们提供了一种以一致且高效的方式组织和构建代码的方法。一些常见的设计模式包括&#xff1a;工厂模式是一种创建型设计模式&#xff0c;它提供用于在超类中创建对象的接口&#xff0c;但允许子类更改将要创建的对象的类型。…

【数据结构趣味多】优先级队列——堆

1. 优先级队列 概念&#xff1a; 队列是一种先进先出(FIFO)的数据结构&#xff0c;但有些情况下&#xff0c;操作的数据可能带有优先级&#xff0c;一般出队列时&#xff0c;可能需要优先级高的元素先出队列&#xff0c;该中场景下&#xff0c;使用队列显然不合适&#xff0c;比…

前端打包后生成的dist 或 build目录,如何在本地启动服务运行

前端打包后生成的dist/build目录&#xff0c;如何在本地启动服务运行 运行npn run build&#xff0c;会打包后会产生 dist 或 build 目录 一般情况下&#xff0c;直接打开dist 或 build 目录下的 index.html会在浏览器看到内容。 然而发现网页一片空白&#xff0c;打开了控制台…

C++基础入门(引用补充)

1、使用场景做参数void Swap(int& left, int& right) {int temp left;left right;right temp; }做返回值int& Count() {static int n 0;n;// ...return n; }c语言内&#xff0c;出了count函数&#xff0c;n被销毁&#xff0c;会创建临时变量存储其值&#xff0…

DETR——使用Transformer进行端到端目标检测的开端之作

深度学习知识点总结 专栏链接: https://blog.csdn.net/qq_39707285/article/details/124005405 此专栏主要总结深度学习中的知识点&#xff0c;从各大数据集比赛开始&#xff0c;介绍历年冠军算法&#xff1b;同时总结深度学习中重要的知识点&#xff0c;包括损失函数、优化器…

寻根究底,为什么Docker中的Alpine Linux镜像能这么小

去年我发表了文章对Docker基础镜像的思考&#xff0c;该不该选择alpine&#xff0c;其中对于Alpine Linux镜像如此之小的原因我解释为它使用了musl而不是glibc 有人发现并指出了我的这个错误&#xff0c;说musl与glibc的大小差别不足以造成如此大的差距&#xff0c;应该别有原…

C++-静态局部变量

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 特征&#xff1a; 1.需添加关键字static。 2.在静态存储区分配内存&#xff0c;始终存在直到程序结束。 3.作用域为局部&#…

阿⾥云Apsara Clouder云计算专项技能认证:云服务器ECS⼊门【 个⼈所得税年度应纳税额抵扣 3600(0成本)】

文章目录 引言I 云服务器ECS⼊门II 考试III 个⼈所得税app填写专项附加扣除引言 适合⼈群:需要交个⼈所得税的上班族,有⼀定计算机基础结果:⼯资年收⼊10-20万的,能省下360元(3600*10%)I 云服务器ECS⼊门 云服务器(Elastic Compute Service, 简称ECS),是一种简单高效,…

PDPS教程:机器人气动点焊焊枪大开与小开运动状态自动切换设置

目录 概述 气动点焊焊枪运动状态设置 机器人气动点焊焊枪工具类型定义 气动点焊焊枪运动状态切换原理 气动点焊焊枪大开与小开状态切换设置 机器人仿真运行 概述 工业机器人点焊焊接过程中&#xff0c;为了提高焊接效率、优化焊接节拍、降低能源消耗&#xff0c;通常会在…

2022尚硅谷SSM框架跟学(八)Spring MVC基础三

2022尚硅谷SSM框架跟学 八 Spring MVC基础三8.RESTful案例8.1准备工作8.2功能清单8.3.具体功能&#xff1a;访问首页(1).配置view-controller(2).创建页面8.4具体功能&#xff1a;查询所有员工数据(1).控制器方法(2).创建employee_list.html8.5具体功能&#xff1a;删除(1).创建…

企业电子招投标采购系统源码之功能模块功能描述

​ 功能模块&#xff1a; 待办消息&#xff0c;招标公告&#xff0c;中标公告&#xff0c;信息发布 描述&#xff1a; 全过程数字化采购管理&#xff0c;打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力&#xff0c;为外…

激光焊接/点焊的特性及优势分析?

目前应用于生产的点焊方式大多为电阻点焊、电弧点焊、激光点焊和胶接点焊等多种点焊方法。其中激光焊接是激光材料加工技术应用的重要方面之一。 激光点焊机主要由激光器、电源及控制、冷却机、导光及调焦、双目体视显微观察几部分构成&#xff0c;结构紧凑&#xff0c;体积小…

Android中对图片的操作,移动、缩放、涂鸦和保存到图库

一、实现方法 监听用户手势&#xff0c;提取用户操作 &#xff08;1&#xff09;移动&#xff1a; 分别计算X,Y轴的结束与初始之间移动偏移的量 &#xff08;2&#xff09;缩放&#xff1a;&#xff08;结束两指间距离伸缩比例&#xff09;/ 初始两指间距离&#xff0c;scaleX…

云计算|OpenStack|社区版OpenStack安装部署文档(五 --- 计算服务nova安装部署---Rocky版)

前言&#xff1a; nova服务是openstack最重要的一个组件&#xff0c;没有之一&#xff0c;该组件是云计算的计算核心&#xff0c;大体组件如下&#xff1a; OpenStack Docs: Compute service overview 挑些重点&#xff0c;nova-api&#xff0c;libvirt&#xff0c;nova-pla…

最小生成树与最短路径

目录 一.最小生成树 1.1概念 1.2Kruskal算法 1.3Prim算法 二.最短路径 2.11单源最短路径--Dijkstra算法 2.1.2单源最短路径--Bellman-Ford算法 一.最小生成树 1.1概念 连通图中的每一棵生成树&#xff0c;都是原图的一个极大无环子图&#xff0c;即&#xff1a;从其中删去…

虹科分享|论企业网络安全的重要性

拥有有效的企业网络安全不仅仅是让你的员工创建一个不是他们宠物名字的密码--除非他们的猫的名字至少有12个字符长&#xff0c;由大小写字母和符号组成。无论是经过充分研究的鱼叉式钓鱼尝试&#xff0c;还是绕过MFA&#xff0c;威胁者都变得更加大胆。随着全球各行业数据泄露事…

判断是否为平衡树

对二叉树有困惑的小伙伴可以看一下我之前的文章&#xff1a;二叉树&#xff08;一&#xff09;_染柒_GRQ的博客-CSDN博客二叉树&#xff08;二&#xff09;_染柒_GRQ的博客-CSDN博客二叉树&#xff08;三&#xff09;_染柒_GRQ的博客-CSDN博客点击上方链接即可查看。题目110. 平…

Ext2explore查看ext2/ext3/ext4 file

比如想查看Android system.img&#xff0c;file看起来是ext2文件&#xff0c;file system.img system.img: Linux rev 1.0 ext2 filesystem data, UUID49e89c77-3dc4-553f-a392-7d11ff348228 (extents) (large files) (huge files)2、windows下怎么看呢&#xff0c;Ext2explore…

Springboot——常用注解及实例

一、常用注解解释&#xff1a;ConfigurationBeanResourceSpringBootApplicationRestControllerRestController 注解包含了原来的 Controller 和 ResponseBody 注解&#xff0c;使用过 Spring 的朋友对 Controller 注解已经非常了解了&#xff0c;这里不再赘述&#xff0c; Resp…

【BSV应用范例】区块链上的自我主权身份

发表时间&#xff1a;2022年6月27日 信息来源&#xff1a;bsvblockchain.org 自我主权身份&#xff08;SSI&#xff09;只是一个空想吗&#xff1f; &#xff08;全球区块链组织联合创始人&#xff09;Jorge Sebastio对此表示&#xff1a;“并非如此&#xff01;” 更重要的是…