C语言第十二课(上):操作符详解【算数、移位、位、赋值操作符】

news2025/2/25 12:23:32

目录

前言:

一、操作符分类:

二、操作符详解:

        1.算术操作符+、-、*、/、%:

        2.移位操作符>>、<<:

        1.原码、反码与补码:

        2.左移操作符:

        3.右移操作符:

        4.警告⚠:

        3.位操作符&、|、^:

        ①.按位与 &:

        ②.按位或 |:

        ③.按位异或 ^:

        ④.作用场景:

        4.赋值操作符与复合赋值操作符:

        ①.赋值操作符:

        ②.复合赋值操作符:

三、总结:


前言:

        我们在前面几篇文章中对井字棋和扫雷两个阶段性练习进行了详细的练习讲解,想必各位小伙伴们对于前面学到的知识也能较为充分的掌握了。从本文开始,我们将继续进行下一部分关于操作符的学习。

一、操作符分类:

        简单来说,操作符可以分为以下十类:

算术操作符移位操作符位操作符
赋值操作符单目操作符关系操作符
逻辑操作符条件操作符逗号表达式
下标引用、函数调用和结构成员

        而在接下来的文章中我也将按照这样的分类和顺序,为各位小伙伴们介绍一些有关操作符的知识。 

二、操作符详解:

        1.算术操作符+、-、*、/、%:

        算术操作符很简单也很常见,是普遍用于我们代码中的各种量的计算的基本运算,其用法也很简单,与我们平日里的算术逻辑相同:

int main()
{
	int a = 10;
	int b = 4;
	int c = 0;
	c = a + b;
	printf("a + b = %d\n", c);
	c = a - b;
	printf("a - b = %d\n", c);
	c = a * b;
	printf("a × b = %d\n", c);
	c = a / b;
	printf("a ÷ b = %d\n", c);
	c = a % b;
	printf("a对b求余 = %d\n", c);
	return 0;
}

        运行结果简单明了:

        这些操作符的使用很简单,但我们在使用时仍需注意一些细节问题。除' % '操作符外,其他几个操作符均可以作用于整数与浮点数,而使用' % '操作符进行计算的两个操作数必须为整数,返回的是整除之后的余数。对于' / '操作符,如果两个操作数均为整数,则执行整数除法,而两个操作数中任意一个(或两个)为浮点数,则执行浮点数除法

int main()
{
	int a = 10;
	int b = 3;
	double c = 3.0;
	printf("a ÷ b = %d\n", a / b);
	printf("a ÷ c = %lf\n", a / c);
    //用lf进行打印的double与float类型浮点数默认打印至小数点后六位
	//在lf前加上"."+打印位数,可以改变为我们希望打印的位数
	printf("a ÷ c = %.1lf\n", a / c);
	return 0;
}

        运行结果验证:

        2.移位操作符>>、<<:

        在这里为各位小伙伴们进行说明,移位操作符中的“位”,指的是二进制位,且移位操作符的操作数只能是整数

        在最开始的学习中,我们提到过,数据在计算机中的存储,存储的是其对应的二进制补码,而移位操作符所操作的,正是各数据的二进制补码。

        1.原码、反码与补码:

        在我们开始细致了解移位操作符之前,我们首先要了解什么是原码,什么是反码,什么又是补码。

        我们都知道,对于一个数,计算机要使用一定的编码方式进行存储,在计算机中通过使用电势的高低来对数据进行存储,高电平为1,低电平为0,则每一位上均存在两种情况,则在32位的计算机中就总共存在着2^32种不同的组合,于是我们在计算机中便可以根据电势的高低来存储数据的二进制码。即原码、反码、补码是机器存储一个具体数字的编码方式。

        在数据存储时,整个二进制码的首位我们将其定为符号位,0表示正数,1表示负数:

+1在32位计算机中的表示为:0000 0000 0000 0000 0000 0000 0000 0001

- 1在32位计算机中的表示为:1000 0000 0000 0000 0000 0000 0000 0001

        这样直接由数据本身转换成的二进制序列即为数据对应的原码

        那么什么是反码呢?正数的反码就是其本身,而负数的反码则是将数据除符号位以外所有位均按位取反后得到的二进制序列:

+1在32位计算机中的反码为:0000 0000 0000 0000 0000 0000 0000 0001

- 1在32位计算机中的反码为: 1111 1111  1111 1111  1111 1111  1111  1110

        最后就是数据的补码了,正数的补码仍是其本身,而负数的补码则是在其反码的基础上+1

 +1在32位计算机中的反码为:0000 0000 0000 0000 0000 0000 0000 0001

- 1在32位计算机中的反码为:  1111 1111  1111 1111  1111  1111  1111 1111

        在我们的计算机中,数据在存储时恰恰存储的是其对应的补码。 

        2.左移操作符:

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

        我们举个例子方便进行研究:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 1;
	int b = a << 1;
	//表示b等于将a向左移动一位
	printf("a = %d b = %d\n", a, b);
	int c = -1;
	int d = c << 1;
	//表示d等于将c向左移动一位
	printf("c = %d d = %d\n", c, d);
	return 0;
}

        其中a的值为1,则其存储在计算机中的补码即为:

+1在32位计算机中的补码为:0000 0000 0000 0000 0000 0000 0000 0001

         b的值为将a左移一位左边抛弃右边补0,即为:

0(抛弃)    000 0000 0000 0000 0000 0000 0000 001    0(补位)

0000 0000 0000 0000 0000 0000 0000 0010

        将其重新化为原码后转换成十进制数即为b的值,其值为2。 

        同理,c的值为-1,其存储在计算机中的补码为:

- 1在32位计算机中的补码为:1111 1111 1111 1111 1111 1111 1111 1111

        而d的值为将c左移一位 ,左边抛弃右边补0,即为:

1(抛弃)    111 1111 1111 1111 1111 1111 1111 111    0(补位)

1111 1111 1111 1111 1111 1111 1111 1110

        将其重新化为原码后转换成十进制数即为b的值,其值为-2。  

        将上述例子编译运行进行验证

        可以看到结果正确,示例得到验证。 

        3.右移操作符:

        与左移操作有所不同,右移操作分为两种:逻辑移位算数移位。我们平常见到基本都是算右移。具体的我们在编写代码时,使用的是逻辑右移还是算术右移,取决于我们所使用的编译器,而我们常用的绝大多数编译器均为算术右移。但是各位小伙伴们在对知识进行学习和了解时,还是应当进行尽可能全面的了解和学习。

        对应的,两种移位的规则也有所不同。在逻辑移位中,与左移操作相似,右边丢弃,左边补0;而在常用的算术移位中,右边丢弃,左边补原本的符号位

        ①.逻辑移位:

        以-1为例:

- 1在32位计算机中的补码为:1111 1111 1111 1111 1111 1111 1111 1111

        将其进行逻辑右移操作,右边丢弃左边补0,即: 

0(补位)    1111 1111 1111 1111 1111 1111 1111 111    1(丢弃)

即 0111 1111 1111 1111 1111 1111 1111 1111

        ②.算术移位:

        我们一直所使用的是Visual Studio 2022版本,在该编译器中为算术右移,则仍使用-1为例:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = -1;
	int b = a >> 1;
	//表示b等于将a向右移动一位
	printf("a = %d b = %d\n", a, b);
	return 0;
}

        其中a的值为-1,则其存储在计算机中的补码即为:

- 1在32位计算机中的补码为:1111 1111 1111 1111 1111 1111 1111 1111

        则b为将a进行算数右移操作,右边丢弃左边补符号位,即:

1(补符号位)    1111 1111 1111 1111 1111 1111 1111 111    1(丢弃)

即 1111 1111 1111 1111 1111 1111 1111 1111

        将其重新化为原码后转换成十进制数即为b的值,其值仍为-1

        我们同样将其编译运行来验证最终结果:

        可以看到,通过运行,我们的示例得到了验证。

        4.警告⚠:

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

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 1;
	int b = a << -1;
	//表示b等于将a向左移动负一位
	printf("a = %d b = %d\n", a, b);
	return 0;
}

        编译运行后的结果不是我们期望得到的结果:

        3.位操作符&、|、^:

        与移位操作相同,位操作符也是针对二进制位进行操作和计算的,且位操作符的操作数同样只能是整数

        首先我们要知道这三种符号的意义:按位与 & 、按位或 | 与按位异或 ^ 

        ①.按位与 &:

        按位与,即将两操作数进行比较,按照各位上的数进行类“与”计算

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 3;
	int b = -5;
	int c = a & b;
	//表示c等于将a与b进行按位与操作
	printf("a = %d b = %d c = %d\n", a, b, c);
	return 0;
}

        其中 的二进制补码为:

+3在32位计算机中的补码为:0000 0000 0000 0000 0000 0000 0000 0011

        b 的二进制补码为:

- 5在32位计算机中的补码为:1111 1111 1111 1111 1111 1111 1111 1011

        则 c 的二进制补码为,a 与 b 每一位均进行与判断均1则为1有0则为0

+3在32位计算机中的补码为:0000 0000 0000 0000 0000 0000 0000 0011

- 5在32位计算机中的补码为: 1111 1111  1111  1111 1111  1111  1111 1011

则 c 在计算机中存储补码为: 0000 0000 0000 0000 0000 0000 0000 0011

        将其重新化为原码后转换成十进制数即为c的值,其值为3

        编译运行来验证结果:

        ②.按位或 |:

         按位或,即将两操作数进行比较,按照各位上的数进行类“或”计算

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 3;
	int b = -5;
	int c = a | b;
	//表示c等于将a与b进行按位或操作
	printf("a = %d b = %d c = %d\n", a, b, c);
	return 0;
}

        其中 的二进制补码为:

+3在32位计算机中的补码为:0000 0000 0000 0000 0000 0000 0000 0011

        b 的二进制补码为:

- 5在32位计算机中的补码为:1111 1111 1111 1111 1111 1111 1111 1011

        则 c 的二进制补码为,a 与 b 每一位均进行或判断1则为10则为0

+3在32位计算机中的补码为:0000 0000 0000 0000 0000 0000 0000 0011

- 5在32位计算机中的补码为: 1111 1111  1111  1111 1111  1111  1111 1011

则 c 在计算机中存储补码为:  1111 1111  1111  1111 1111  1111  1111 1011

        将其重新化为原码后转换成十进制数即为c的值,其值为-5

        编译运行起来验证结果:

        ③.按位异或 ^:

        按位异或,即将两操作数进行比较,按照各位上的数进行类“异或”计算

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 3;
	int b = -5;
	int c = a ^ b;
	//表示c等于将a与b进行按位异或操作
	printf("a = %d b = %d c = %d\n", a, b, c);
	return 0;
}

        其中 的二进制补码为:

+3在32位计算机中的补码为:0000 0000 0000 0000 0000 0000 0000 0011

        b 的二进制补码为:

- 5在32位计算机中的补码为:1111 1111 1111 1111 1111 1111 1111 1011

        则 c 的二进制补码为,a 与 b 每一位均进行异或判断相异为1相同为0

+3在32位计算机中的补码为:0000 0000 0000 0000 0000 0000 0000 0011

- 5在32位计算机中的补码为: 1111 1111  1111  1111 1111  1111  1111 1011

则 c 在计算机中存储补码为:  1111 1111  1111  1111 1111  1111  1111 1000

        将其重新化为原码后转换成十进制数即为c的值,其值为-8

        编译运行验证结果:

        ④.作用场景:

        曾经有这样一道题目,各位小伙伴们一起来思考一下该如何去处理:

不能创建临时变量,实现两个数的交换。

        这道题目我们该怎样去实现呢?答案是通过连续使用位操作符异或' ^ '来实现:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 10;
	int b = 20;
    printf("a = %d b = %d\n", a, b);
	//连续使用位操作符异或'^'
	a = a ^ b;
	b = b ^ a;
	a = a ^ b;
	printf("a = %d b = %d\n", a, b);
	return 0;
}

        我们将他编译运行起来看看其结果:

        可以看到,通过连续的使用位操作符,完美的实现了我们的期望功能。

        4.赋值操作符与复合赋值操作符:

        ①.赋值操作符:

        赋值操作符' = '很简单,但也是极其实用的一种操作符,它可以帮助我们将之前赋予的一个我们不满意的值进行修改,即我们可以自己重新进行赋值,且赋值操作符可以连续使用

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 10;
	int b = 20;
	int c = 0;
	int d = 0;
	printf("a = %-2d b = %-2d c = %-2d d = %-2d\n", a, b, c, d);
	a = c = b + 10;
	//赋值操作符可以连续使用
	d = a;
	printf("a = %-2d b = %-2d c = %-2d d = %-2d\n", a, b, c, d);
	return 0;
}

        编译运行:

        ②.复合赋值操作符:

        例如+、-、*、/、%、>>、<<、&、|、^等,这些运算符都可以和赋值运算符组成复合赋值操作符+=-=*=/=%=>>=<<=&=|=^=,且同样有效:

#define _CRT_SECURE_NO_WARNINGS 1

#include<stdio.h>

int main()
{
	int a = 10;
	int b = 20;
	printf("a = %-2d b = %-2d c = %-2d d = %-2d\n", a, b);
	a += b;
	printf("a = %d\n", a);
	a = 10;
	a -= b;
	printf("a = %d\n", a);
	a = 10;
	a *= b;
	printf("a = %d\n", a);
	a = 10;
	a /= b;
	printf("a = %d\n", a);
	a = 10;
	a %= b;
	printf("a = %d\n", a);
	a = 10;
	a >>= b;
	printf("a = %d\n", a);
	a = 10;
	a <<= b;
	printf("a = %d\n", a);
	a = 10;
	a &= b;
	printf("a = %d\n", a);
	a = 10;
	a |= b;
	printf("a = %d\n", a);
	a = 10;
	a ^= b;
	printf("a = %d\n", a);
	return 0;
}

        编译运行:

三、总结:

        至此,我们今天关于算数、移位、位和赋值操作符的介绍就到此为止了,这些操作符应用极其广泛,是我们编写代码过程中的好帮手,希望各位下伙伴们下去以后多多思考和理解,勤加练习,熟练掌握相关的原理和用法,提高自己的代码编写工作效率。

        希望各位小伙伴们能从今天的介绍中获得一些收获和启发,我也十分荣幸能为各位小伙伴们的学习生活提供一些帮助。奋斗者在汗水汇集的江河里,将事业之舟驶到了理想的彼岸!

        新人初来乍到,辛苦各位小伙伴们动动小手,三连走一走 ~ ~ ~  最后,本文仍有许多不足之处,欢迎各位看官老爷随时私信批评指正!

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

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

相关文章

Qt5开发从入门到精通——第十二篇三节(Qt5 事件处理及实例——多线程应用、服务器端编程、客户端编程)

提示&#xff1a;欢迎小伙伴的点评✨✨&#xff0c;相互学习c/c应用开发。&#x1f373;&#x1f373;&#x1f373; 博主&#x1f9d1;&#x1f9d1; 本着开源的精神交流Qt开发的经验、将持续更新续章&#xff0c;为社区贡献博主自身的开源精神&#x1f469;‍&#x1f680; 文…

用DIV+CSS技术设计的抗击疫情网页与实现制作(web前端网页制作课作业)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

基于C++实现的游客信息管理系统

目 录 一、 项目技术路线说明 1 二、 项目需求分析 2 2.1 项目介绍 2 2.2 功能需求 2 三、 系统分析与设计 3 3.1 本程序需解决的关键技术问题 3 3.2 程序流程 3 3.2.1 注册或登陆流程图 3 3.2.2 信息日期判断流程图 4 3.2.3 操作功能选择模块 5 3.3 功能模块 6 3.3.1 增删改查…

让Unity打包AssetBundle更轻松

AssetBundle作用1、AssetBundle是一个压缩包包含模型、贴图、预制体、声音、甚至整个场景&#xff0c;可以在游戏运行的时候被加载&#xff1b; 2、AssetBundle自身保存着互相的依赖关系&#xff1b; 3、压缩包可以使用LZMA和LZ4压缩算法&#xff0c;减少包大小&#xff0c;更快…

HTML小游戏13 —— 仿《神庙逃亡》3D风格跑酷游戏《墓地逃亡》(附完整源码)

&#x1f482; 网站推荐:【神级源码资源网】【摸鱼小游戏】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 想寻找共同学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】&#x1f4ac; 免费且实用的计…

BGP服务器

BGP服务器被称为“边界网关协议”(BGP)&#xff0c;是一种用于在不同主机网关、 Internet或自治系统之间传输数据和信息的路由协议。 BGP是一种路径矢量协议(PVP)&#xff0c;它维护不同主机、网络和网关的路由器的路径&#xff0c;并根据 BGP做出路由决定。把电信、联通、联通…

算法day32|122,55,45

122.买卖股票的最佳时机II class Solution:def maxProfit(self, prices: List[int]) -> int:profit 0for i in range(len(prices)-1):diff prices[i1]-prices[i]if diff > 0:profit diffelse:profit 0return profit 简单到我不敢相信。 本题解法很巧妙&#xff0c;大…

Redis实战——缓存

目录 1 前言 1.1什么是缓存&#xff1f; 1.2 缓存的作用及成本 1.3 Redis缓存模型 2 给商户信息添加缓存 3 缓存更新策略 3.1 更新策略介绍 3.2 主动更新策略 3.3 主动更新策略练习 4 缓存穿透及其解决方案 4.1 缓存穿透的概念 4.2 解决方案及实现 5 缓存雪崩的…

C++:STL::String模拟实现

前言&#xff1a; 浅拷贝和深拷贝 实现string需要知道深浅拷贝问题。观察如下自命名空间中实现的string&#xff0c;不自写string的string类型参数的构造函数&#xff0c;编译器会默认生成&#xff0c;做浅拷贝。对于自定义类型使用自定义类型的构造函数&#xff0c;如果是默认…

基于遗传算法的PID控制器增益的实现(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

【信息量判别块:语义监督:GAN:IVIF】

Semantic-supervised Infrared and Visible Image Fusion via a Dual-discriminator Generative Adversarial Network &#xff08;通过双重鉴别器生成对抗网络进行语义监督的红外和可见光图像融合&#xff09; 我们提出了一种新的端到端模型&#xff0c;以在红外和可见光图像…

java序列化,看这篇就够了

面试官&#xff1a;兄弟&#xff0c;说说你对transient的理解和感悟 哪吒&#xff1a;what&#xff1f;还有感悟&#xff1f; 先说结论&#xff0c;在序列化、反序列化时&#xff0c;被transient关键字修饰的成员属性变量不会被序列化。 面试官&#xff1a;这就完了&#xf…

Flutter高仿微信-第51篇-群聊-修改群名

Flutter高仿微信系列共59篇&#xff0c;从Flutter客户端、Kotlin客户端、Web服务器、数据库表结构、Xmpp即时通讯服务器、视频通话服务器、腾讯云服务器全面讲解。 详情请查看 效果图&#xff1a; 实现代码&#xff1a; //修改群名 void _updateGroupName(){bool isOwner fals…

Multi-Interest Network with Dynamic Routing forRecommendation at Tmall 论文阅读笔记

1. ABSTRACT 1.1 Industrial recommender systems &#xff08;1&#xff09;工业推荐系统通常由匹配阶段和排名阶段组成&#xff1b; &#xff08;2&#xff09;匹配阶段&#xff1a;检索与用户兴趣相关的候选项&#xff1b; &#xff08;3&#xff09;排名阶段&#xff1a;…

Spring Cloud OpenFeign - - - > 日志配置

项目源码地址&#xff1a;https://download.csdn.net/download/weixin_42950079/87168704 OpenFeign 有 4 种日志级别&#xff1a; NONE: 不记录任何日志&#xff0c;是OpenFeign默认日志级别&#xff08;性能最佳&#xff0c;适用于生产环境&#xff09;。BASIC: 仅记录请求方…

BT - Unet:生物医学图像分割的自监督学习框架

BT-Unet采用Barlow twin方法对U-Net模型的编码器进行无监督的预训练减少冗余信息&#xff0c;以学习数据表示。之后&#xff0c;对完整网络进行微调以执行实际的分割。 BT-Unet由 Indian Institute of Information Technology Allahabad开发&#xff0c;发布在2022年的JML上 …

相关性质和条件变量-ReentrantLock详解(2)-AQS-并发编程(Java)

文章目录1 可重入2 可打断3 公平锁4 条件变量4.1 await()4.1.1 主方法4.1.2 addConditionWaiter()4.1.3 isOnSyncQueue()4.1.4 checkInterruptWhileWaiting()4.2 signal()4.2.1 主方法4.2.2 doSignal()4.2.3 transferForSignal()5 后记1 可重入 可重入在加锁中体现代码如下&am…

零经验,小白变大厨!

平时煮泡面都会翻车的老王      昨天在朋友圈po了一组美食图      朋友小聚,20分钟搞定一桌菜,嘻嘻。      我点开一看,嚯!      红烧里脊、糖醋排骨、油焖大虾、剁椒鱼头……个顶个的硬菜,而且色泽诱人看起来很好吃的样子,关键是居然20分钟搞定?      难…

2022 高教杯数学建模C题古代玻璃制品的成分分析与鉴别回顾及总结

2022 高教杯数学建模C题古代玻璃制品的成分分析与鉴别回顾及总结 Paper & Code&#xff1a;https://github.com/Fly-Pluche/2022-mathematical-modeling-C 希望可以施舍几个star⭐️ 国赛分工 我们三人都有主要的分工: 队员A主要负责二&#xff0c;三问的求解以及代码的编…

被问到可重入锁条件队列,看这一篇就够了!|原创

本文深入解读了高频面试点——ReentrantLock的条件队列使用方法及其原理。源码有详细注释&#xff0c;建议收藏阅读。点击上方“后端开发技术”&#xff0c;选择“设为星标” &#xff0c;优质资源及时送达Jdk中独占锁的实现除了使用关键字synchronized外,还可以使用ReentrantL…