第五节 操作符

news2024/11/22 6:22:58

第五节 操作符



目录

  • 一. 操作符分类
  • 二. 算术操作符
  • 三. 移位操作符
    • 1. 二进制位
    • 2. 左移操作符
    • 3. 右移操作符
  • 四. 位操作符
    • 1. 按位与
    • 2. 按位或
    • 3. 按位异或
  • 五. 赋值操作符
  • 六. 单目操作符
    • 1. 概述
    • 2. sizeof是操作符而不是函数
    • 3. ~对一个数的二进制按位取反
    • 4. ++与- -
    • 5. sizeof和数组
  • 七. 关系操作符
  • 八. 逻辑操作符
  • 九. 条件操作符
  • 十. 逗号表达式
  • 十一. 下标引用、函数调用和结构成员
    • 1. [ ] 下标引用操作符
    • 2. ( ) 函数调用操作符
    • 3. 访问一个结构的成员
  • 十二. 表达式求值
    • 1. 隐式类型转换
    • 2. 算术转换
    • 3. 操作符的属性



本章重点:
各种操作符的介绍
表达式求值


一. 操作符分类

算术操作符 + - * / %
移位操作符 >> <<
位操作符 & | ^
赋值操作符 = += -= *= /=
单目操作符 ! size of ++ --
关系操作符 > < >= <= == !=
逻辑操作符 && ||
条件操作符 ? :
逗号表达式 ,
下标引用、函数调用和结构成员 [] () . ->


二. 算术操作符

+ - * / %

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


三. 移位操作符

<< 左移操作符
>> 右移操作符

注:移位操作符的操作数只能是整数。

1. 二进制位

整数的二进制表现形式一共有三种,原码、反码和补码。
原码:按照数值的正负,直接写出的二进制序列就是原码。
反码:原码的符号位不变,其他位按位取反。
补码:反码的二进制+1就得到了补码。

对于有符号的整数来说,最高位的1位是符号位。
符号位是1表示负数
符号位是0表示正数。
对于无符号整数来说,没有符号位,所有位都是有效位。

对于正的整数,原码、反码和补码相同,无需计算。
对于负的整数,原码、反码和补码是需要计算的。

整数在内存中存储的都是补码的二进制序列。
整数在计算的时候也使用的是补码!


2. 左移操作符

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

代码如下:

#include<stdio.h>
int main() {
	int m = 7;
	int n = m << 1;
	printf("%d\n",m);
	printf("%d",n);
	return 0;
}

运行结果如下:

在这里插入图片描述


#include<stdio.h>
int main() {
	int m = -7;
	int n = m << 1;
	printf("%d\n",m);
	printf("%d",n);
	return 0;
}

运行结果如下:

在这里插入图片描述


m在没被赋值的情况下自身的值不会被改变。


多写几组代码进行比对。发现,对于正整数而言,左移一位操作运算就是乘2。再次深入研究,发现正整数左移运算的效果就是将原整数的值乘以2的指定次幂。例如,将一个整数n左移k位,相当于将n乘以2的k次方。对于负整数而言,左移一位操作运算也是乘2。


3. 右移操作符

右移操作符分两种方式:一种是算数右移,另一种是逻辑右移
逻辑右移:右边直接丢弃,左边补0
算数右移:左边用原该值的符号位填充,右边丢弃

不同的编译器,采用的右移方式也不同。绝大部分编译器采用的是算数右移。


vs2019采用的是算数右移,代码如下:

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

运行成功,结果如下:

在这里插入图片描述


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

例如:

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


四. 位操作符

位操作符有:
按位与 &
按位或 |
按位异或 ^

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


1. 按位与

代码如下:

#include<stdio.h>
int main()
{
	int a = 3;
	int b = -5;
	int c = a & b;//按(2进制)位与
	//00000000000000000000000000000011 --- 3的补码
	//10000000000000000000000000000101 
	//11111111111111111111111111111010
	//11111111111111111111111111111011 --- -5的补码
	//00000000000000000000000000000011 --- 3的补码
	//00000000000000000000000000000011
	printf("%d\n", c);
	return 0;
}

运行代码成功,结果如下:

在这里插入图片描述


我们可以利用按位与得出二进制位的最后一位,代码如下:

#include<stdio.h>
int main()
{
	int a = 3;
	//a&1
	//00000000000000000000000000000011 --- 3的补码
	//00000000000000000000000000000001
	return 0;
}

要是要用到其他二进制位,可以先位移,再按位与。


2. 按位或

代码如下:

#include<stdio.h>
int main()
{
	int a = 3;
	int b = -5;
	//00000000000000000000000000000011 --- 3的补码
	//10000000000000000000000000000101 
	//11111111111111111111111111111010
	//11111111111111111111111111111011 --- -5的补码
	int c = a | b;
	//00000000000000000000000000000011 --- 3的补码
	//11111111111111111111111111111011 --- -5的补码
	//11111111111111111111111111111011 
	//11111111111111111111111111111010
	//10000000000000000000000000000101   -5
	//11111111111111111111111111111011
	//10000000000000000000000000000100
	//10000000000000000000000000000101
	printf("%d\n", c);
	return 0;
}

运行结果成功,结果如下:

在这里插入图片描述


3. 按位异或

相同为0,相异为1

代码如下:

#include<stdio.h>
int main()
{
	int a = 3;
	int b = -5;
	//00000000000000000000000000000011 --- 3的补码
	//10000000000000000000000000000101 
	//11111111111111111111111111111010
	//11111111111111111111111111111011 --- -5的补码
	int c = a ^ b;
	//00000000000000000000000000000011
	//11111111111111111111111111111011
	//11111111111111111111111111111000
	//10000000000000000000000000000111
	//10000000000000000000000000001000
	printf("%d\n", c);
	return 0;
}

运行代码成功,结果如下:

在这里插入图片描述


注意:
a^a = 0
0^a = a


有一道很有意思的面试题,题目如下:

不能创建临时变量(第三个变量),实现两个数的交换。
代码如下:

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

运行代码成功,结果如下:

在这里插入图片描述


五. 赋值操作符

使用赋值操作符需要注意一些编码规范,例如:

a = x = y+1; 

这样的连续赋值代码感觉怎么样?

那同样的语义,你看看:

x = y+1;
a = x;

这样的写法是不是更加清晰爽朗而且易于调试。


六. 单目操作符

1. 概述

! 逻辑反操作
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
– 前置、后置–
++ 前置、后置++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换


2. sizeof是操作符而不是函数

代码证明如下:

#include <stdio.h>
int main()
{
	int a = 10;
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof a);//后面的括号在括号中写的不是类型的时候,括号可以省略,这样就说sizeof不是函数。
	return 0;
}

代码运行成功,结果如下:

在这里插入图片描述


3. ~对一个数的二进制按位取反

代码如下:

#include<stdio.h>
int main()
{
	int a = 0;
	printf("%d\n", ~a);
	//0
	//00000000000000000000000000000000
	//11111111111111111111111111111111
	//10000000000000000000000000000000
	//10000000000000000000000000000001
	//-1
	return 0;
}

运行成功,结果如下:

在这里插入图片描述


4. ++与- -

++ 操作是是一种自增1的操作。
前置++:计算口诀:先+1,后使用
前置--:先-1,后使用
后置++:计算口诀:先使用,后+1
后置--:先使用,后-1

非常规自增自减:https://danbaku.blog.csdn.net/article/details/131756318


5. sizeof和数组

代码如下:

#include<stdio.h>
void test1(int arr[])
{
	printf("%d\n", sizeof(arr));//(2)
}
void test2(char ch[])
{
	printf("%d\n", sizeof(ch));//(4)
}
int main()
{
	int arr[10] = { 0 };
	char ch[10] = { 0 };
	printf("%d\n", sizeof(arr));//(1)
	printf("%d\n", sizeof(ch));//(3)
	test1(arr);
	test2(ch);
	return 0;
}

运行成功,结果如下:

x86环境

在这里插入图片描述

x64环境

在这里插入图片描述


七. 关系操作符

>
>=
<
<=
!=
==

注意:在编程的过程中==和=不小心写错,导致的错误。


八. 逻辑操作符

&& 逻辑与
|| 逻辑或

注意:区分逻辑与和按位与,区分逻辑或和按位或

1&2------>0
1&&2---->1
1|2------->3
1||2------>1


360面试题一道,代码如下:

#include<stdio.h>
int main()
{
    int i = 0, a = 0, b = 2, c = 3, d = 4;
    i = a++ && ++b && d++;
    printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
    return 0;
}

运行成功,结果如下:

在这里插入图片描述

&&左边为假(0),右边就不算了。


#include <stdio.h>
int main()
{
    int i = 0, a = 1, b = 2, c = 3, d = 4;
    i = a++||++b||d++;
    printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
    return 0;
}

代码运行成功,结果如下:

在这里插入图片描述

||左边为真(1),右边就不算了。


短路操作:
&& 左边操作数如果为假,右边无需计算
||    左边操作数如果为真,右边无需计算
详见博客:https://danbaku.blog.csdn.net/article/details/135054294


九. 条件操作符

exp1 ? exp2 : exp3
条件操作符也叫三目运算符,常常用于两个数中找较大值。


十. 逗号表达式

exp1, exp2, exp3, …expN

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

代码如下:

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

运行代码成功,结果如下:

在这里插入图片描述


逗号表达式的实际应用:

可以将:

a = get_val();
count_val(a);
while (a > 0)
{   
	//业务处理
	a = get_val();
	count_val(a);
}

改写为:

while (a = get_val(), count_val(a), a > 0)
	{
		//业务处理
	}


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

1. [ ] 下标引用操作符

操作数:一个数组名 + 一个索引值


2. ( ) 函数调用操作符

接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。


3. 访问一个结构的成员

. 结构体.成员名
-> 结构体指针->成员名

代码如下:

#include<stdio.h>
struct Book
{
	char name[20];
	int price;
};

//结构体变量.成员
//结构体指针->成员

void Print(struct Book* pb)
{
	printf("%s %d\n", (*pb).name, (*pb).price);
	printf("%s %d\n", pb->name, pb->price);
}

int main()
{
	struct Book b = {"C语言指南", 55};
	printf("%s %d\n", b.name, b.price);
	Print(&b);
	return 0;
}

代码运行成功,结果如下:

在这里插入图片描述


十二. 表达式求值

表达式求值的顺序一部分是由操作符的优先级和结合性决定。
同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。

1. 隐式类型转换

整形提升详见博客:https://danbaku.blog.csdn.net/article/details/135055042


2. 算术转换

  如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。下面的层次体系称为寻常算术转换。

long double
double
float
unsigned long int
long int
unsigned int
int

如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算


3. 操作符的属性

复杂表达式的求值有三个影响的因素。
操作符的优先级
操作符的结合性
是否控制求值顺序

两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。

一些问题表达式详见博客:https://danbaku.blog.csdn.net/article/details/135083672



本篇博客为本人学习C语言时的详细笔记,如有错误之处,还望各位指正。
文章为原创,如要转载请注明出处

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

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

相关文章

【Spring教程31】SSM框架整合实战:从零开始学习SSM整合配置,如何编写Mybatis SpringMVC JDBC Spring配置类

目录 1 流程分析2 整合配置2.1 步骤1&#xff1a;创建Maven的web项目2.2 步骤2:添加依赖2.3 步骤3:创建项目包结构2.4 步骤4:创建SpringConfig配置类2.5 步骤5:创建JdbcConfig配置类2.6 步骤6:创建MybatisConfig配置类2.7 步骤7:创建jdbc.properties2.8 步骤8:创建SpringMVC配置…

k8s安装配置dashboard

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

kali-捆绑应用程序

文章目录 一、安装开发环境二、开始捆绑三、开始监听 操作环境 kali windows 一、安装开发环境 ┌──(kali㉿kali)-[~] └─$ sudo -i [sudo] kali 的密码&#xff1a;┌──(root㉿kali)-[~] └─# whoami root┌──(root㉿kali)-[~] └─# apt update …

(七)STM32 NVIC 中断、优先级管理及 AFIO 时钟的开启

目录 1. 中断相关知识简介 1.1 什么是中断 1.2 什么是内中断、外中断 1.3 什么是可屏蔽中断、不可屏蔽中断 2. CM3 内核中断介绍 2.1 F103系统异常清单 2.2 F103 外部中断清单 3. NVIC 简介 3.1 NVIC 寄存器简介 3.2 NVIC 相关寄存器的介绍 4. 中断优先级 4.1 优先…

uni-app 用于开发H5项目展示饼图,使用ucharts 饼图示例

先下载ucharts H5示例源码&#xff1a; uCharts: 高性能跨平台图表库&#xff0c;支持H5、APP、小程序&#xff08;微信小程序、支付宝小程序、钉钉小程序、百度小程序、头条小程序、QQ小程序、快手小程序、360小程序&#xff09;、Vue、Taro等更多支持canvas的框架平台&#…

洛谷 P8794 [蓝桥杯 2022 国 A] 环境治理

文章目录 [蓝桥杯 2022 国 A] 环境治理题目链接题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示 思路解析CODE给点思考 [蓝桥杯 2022 国 A] 环境治理 题目链接 https://www.luogu.com.cn/problem/P8794 题目描述 LQ 国拥有 n n n 个城市&#xff0c;从 0 0 …

【无标题】CTF之SQLMAP

拿这一题来说 抓个包 复制报文 启动我们的sqlmap kali里边 sqlmap -r 文件路径 --dump --dbs 数据库 --tables 表

【老牌期刊】IF:6+,2天预审,3-5个月录用!

期刊简介 1区计算机智能类SCI 【期刊概况】IF&#xff1a;6.0-7.0&#xff0c;JCR1区&#xff0c;中科院2区&#xff1b; 【终审周期】走期刊部系统&#xff0c;3个月左右录用&#xff1b; 【检索情况】SCI检索&#xff1b; 【WOS收录年份】2018年&#xff1b; 【自引率】…

远程桌面连接软件除了Todesk还能用什么?

自从昨天Todesk开始报错&#xff0c;开始寻找好用的远程桌面连接软件&#xff0c;目前尝试了解到的免费的有RayLink和Teamviewer&#xff1a; TeamViewer&#xff1a;就个人来讲&#xff0c;感觉用户体验不是很友好 &#xff1a; 有什么好用的免费的远程桌面连接软件&#xff0…

html中RGB和RGBA颜色表示法

文章目录 RGB什么是RGBRGB颜色模式的取值范围RGB常用颜色对照表 RGBA什么是RGBARGBA颜色模式的取值范围 总结 RGB 什么是RGB RGB是一种颜色空间&#xff0c;其中R代表红色&#xff08;Red&#xff09;、G代表绿色&#xff08;Green&#xff09;、B代表蓝色&#xff08;Blue&a…

外汇天眼:芝加哥商品交易所(CME)对鹰七公司规定进行罚款

国际衍生品市场CME集团发布了一则关于Eagle Seven LLC的纪律行动通知。根据一项和解提议&#xff0c;其中Eagle Seven LLC既未承认也未否认任何违规规定或事实陈述&#xff0c;纽约商业交易所&#xff08;NYMEX&#xff09;业务行为委员会的一个小组认定&#xff0c;在2022年2月…

非专业的建模人员如何给模型设置材质纹理贴图?

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 1、材质和纹理的区别于关联 材质&#xff08;Material&#xff09;是…

【HarmonyOS开发】ArkTs实现侧栏联动

侧栏联动功能模块&#xff1a; 1、切换左侧导航&#xff0c;右侧滚动到对应的内容。 2、滚动右侧的内容&#xff0c;左侧会切换对应的导航。 1、涉及知识点 List&#xff08;列表组件&#xff09;、ListItemGroup&#xff08;列表item分组&#xff09; 2、效果预览 3…

AI数字人短视频矩阵怎么做?

AI数字人是什么&#xff1a;你可以通过我们的系统克隆出多个AI形象&#xff0c;每个数字人都有独特的个性和风格。无论是批量制作短视频&#xff0c;还是直播7*24小时都可以。数字人就是用AI技术根据你的真人形象克隆出一个数字人&#xff0c;跟真人的相似度可以达到100&#x…

【FAQ】运动健康服务云侧数据常见问题及解答

目录 Q1&#xff1a;v2接口相比于v1接口传参及返回的数据格式有变化吗&#xff1f;是否可以直接将v1接口改成v2接口&#xff1f; Q2&#xff1a;如何获取采集健康数据的穿戴设备信息&#xff1f; Q3&#xff1a;如何处理非华为手机产生的步数调用采样明细接口查询不到数据&a…

STM32-I2C通讯-AHT20温湿度检测

非常感谢&#xff0c;提供的视频学习 https://www.bilibili.com/video/BV1QN411D7ak/?spm_id_from333.788&vd_source8ca4826038edd44bb618801808a5e076 该文章注意&#xff1a;串口显示中文会乱码&#xff0c;必须选用支持ASCII的串口助手&#xff0c;才能正常显示中文。…

软考真的只准计算机专业报考吗?其实你也可以!

因为软考的全称为计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff0c;很多人误以为软考只允许计算机专业的人报考&#xff0c;实际上并非如此~ 首先&#xff0c;让我们一起来看一下软考的报考条件 软考报考条件 软考的报考条件相对宽松&#xff0c;有…

自动化测试知识总结(含资料)

一、自动化测试 自动化测试的定义&#xff1a;使用一种自动化测试工具来验证各种软件测试的需求&#xff0c;它包括测试活动的管理与实施、测试脚本的开发与执行。 自动化测试只是测试工作的一部分&#xff0c;是对手工测试的一种补充; 自动化测试绝不能代替手工测试;多数情况…

【Mybatis】日常知识点随笔(持续更新)

目录 【K】Mybatis使用Select注解书写简单sql 【K】MySQL 数据类型与 Java 类型的对应关系 【K】Mybatis相同代码复用 1. 定义公共 SQL 片段 2. 引用公共 SQL 片段 3. 使用参数 4. 复用和组合 5. 注意事项 【K】mysql如何实现插入一条数据后立刻获取该数据自增长id进行…

软件测试面试:测试基础题

软件测试的流程是什么&#xff1f;&#xff08;测试流程&#xff09; &#xff08;1&#xff09;需求调查&#xff1a;全面了解系统概况、应用领域、软件开发周期、软件开发环境、开发组织、时间安排、功能需求、性能需求、质量需求及测试要求等。根据系统概况进行项目所需的人…