C语言操作符(上)

server/2025/2/3 10:10:04/

操作符

  • 一,操作符的分类
    • 1,算数操作符
    • 2,赋值操作符
    • 3,逻辑操作符
    • 4,条件操作符
    • 4,单目操作符
    • 5,函数调用和下表访问操作符
  • 二,原码反码补码
  • 三,移位操作符
    • 1,左移操作符
    • 2,右移操作符
  • 四,位操作符
    • 1,&按位与的妙用
    • 2,|按位或的妙用

一,操作符的分类

C语言中提供的操作符有一下这么几种:
• 算术操作符: + 、- 、* 、/ 、%
• 移位操作符: << >>
• 位操作符: & | ^
• 赋值操作符: = 、+= 、 -= 、 = 、 /= 、%= 、<<= 、>>= 、&= 、|= 、^=
• 单⽬操作符: !、++、–、&、
、+、-、~ 、sizeof、(类型)
• 关系操作符: > 、>= 、< 、<= 、 == 、 !=
• 逻辑操作符: && 、||
• 条件操作符: ? :
• 逗号表达式: ,
• 下标引⽤: []
• 函数调⽤: ()
• 结构成员访问: . 、->
看到这些操作符相信有一些是你已经见过并熟练掌握的,但还有一些涉及到位运算的操作符你可能是初次见到。像移位操作符,逗号表达式,位操作符等,本篇文章重点来讲述涉及到位的操作符。
我们先来花小部分篇幅来讲算术操作符、赋值操作符、逻辑操作符、条件操作符和部分的单⽬操作符。

1,算数操作符

算术操作符有这几种分别为: + 、- 、* 、/ 、%唯一需要注意的就是取模运算,计算结果得到的是余数。
通过重复除10模10(/10%10)这两个算数运算符可以获得一个多位数的每一位!

2,赋值操作符

赋值操作符有以下几种分别为:= 、+= 、 -= 、 *= 、 /= 、%= 、<<= 、>>= 、&= 、|= 、^= 。这种写法其实是n=n+m简写成n+=m的写法。赋值运算符要和关系运算符分开,很多初学者搞不清一个等号和两个等号。
一个等号 = -> 赋值
两个等号 ==-> 判断相等

其中包含的<<,>>,&,^是稍后要介绍的设计位的操作符。

3,逻辑操作符

逻辑操作符有两种: && 、||。&&叫逻辑与 ||叫逻辑或
逻辑操作符主要关心的是布尔值,布尔值True表示真,False表示假,而计算机是二进制只有0和1来表示所以1表示真,0表示假。
所以逻辑操作符在运算的时候有几种情况: 0&&0为0 1&&0为0 1||0为1 0||0为0
在学逻辑操作符还要记住一句话,逻辑与有假为假,逻辑或有真为真,非零即真。

4,条件操作符

条件操作符主要为: ? : 。这个操作符具体形式为:表达式?结果一:结果二。
举个简单的例子:

int main()
{int a = 3;int b = 5;int c = 0;c = a > b ? a : b;printf("%d", c);printf("\n");return 0;
}

在这里插入图片描述
从运行结果来看得到的值为5,那为什么是5呢/我们来分析一下代码:
a>b?a:b 从左到右?意思是表达式左边的值为真吗?也就是a是大于b的吗?如果大于结果为a,再将a赋值给c,如果小于,结果为b,再将b赋值给a。
总结:
所以 表达式?结果一:结果二表达式为真,执行结果一;表达式为假,执行结果二。

4,单目操作符

单⽬操作符有以下几种: !、++、–、&、*、+、-、~ 、sizeof、(类型)。其中也有一些位操作符,我们稍后介绍。还有一些像自增,自减已经在之前就介绍过。其中比较重要的就是sizeof和~取反操作。

1. sizeof是用来计算类型大小的,比如sizeof(int/short/long/double)。sizeof也经常用来计算数组元素的个数。
**2. ~取反操作,就是将以二进制形式存储的数据进行取反操作。**这点等介绍完了原码反码补码之后你就会明白了。
3,还要注意的是如果sizeof里面有表达式是不参与计算的,因为sizeof在编译阶段就直接返回类型的大小了,比如int类型大小为4。而表达式计算是在运行时才计算的。

5,函数调用和下表访问操作符

函数调用和下标访问操作符在之前的文章有讲到过,可以参考之前的文章。
传送门函数:函数
传送门数组:数组

二,原码反码补码

在介绍设计位操作符之前我门先要了解数据在计算机的存储形式,上一篇文章我们详细介绍了进制转换,有了进制转换的知识就为我们下面的学习打下了基础。如果还不了解进制转换可以去看上一篇文章:传送门。

在上一篇文章中我们介绍了计算机的底层实际上就是电路,而电路只有高电平和低电平两种状态这就与二进制相似只有0和1这两种状态。这时可能有人问计算机是怎么存储数据的呢?比如在我们写代码的时候我们通常会定义一个变量然后给它赋值,那这个值是怎样存储的呢?

首先来介绍一下什么是原码,反码,补码:

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

整数的2进制表示方法有三种,即原码、反码和补码 有符号整数的三种表示方法均有符号位和数值位两部分,2进制序列中,最高位的1位是被当做符号 位,剩余的都是数值位。 符号位都是⽤0表⽰“正”,⽤1表⽰“负”。一个整型数是占4个字节 一个字节占8比特位 所以是由32位二进制来构成 举个例子:
在这里插入图片描述
而整数又分为有符号整数和无符号整数这两种,而有符号数又分为正整数和负整数这两种。在这里插入图片描述

  • 正整数的原、反、补码都相同。
  • 负整数的三种表方法各不相同。
  • 负整数取反加一为补码 补码取反加一为原码。
    我们来看一个简单的运算:
#include<stdio.h>
int main()
{int a = 10;int b = -5;//10的原码00000000000000000000000000001010//因为10为整数 原码=反码=补码//-5的原码10000000000000000000000000000101//-5的反码11111111111111111111111111111010//-5的补码11111111111111111111111111111011int c=a+b;//a+b 是补码运算//10的补码       00000000000000000000000000001010//-5的补码       11111111111111111111111111111011//相加之后的补码:100000000000000000000000000000101 最左边多出的一位将丢弃掉所以符号位为0是正整数 原反补都相同,直接读出101对应的值是5printf("%d",c);return 0;
}

在这里插入图片描述
由此我们可以总结:
在这里插入图片描述
但是数据存放内存中其实存放的是补码这是为什么呢?

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

三,移位操作符

1,左移操作符

移位规则:左边抛弃、右边补0;来看一段代码:

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

在这里插入图片描述
从结果上看不知各位读者看出来了吗就是左移是不会改变原来的值。我们给出具体分析
在这里插入图片描述

2,右移操作符

移位规则:⾸先右移运算分两种:

  1. 逻辑右移:左边⽤0填充,右边丢弃
  2. 算术右移:左边⽤原该值的符号位填充,右边丢弃
    一般情况下都是算数右移动。下面来看代码;
#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位演⽰ 
//警告:对于移位运算符,不要移动负数位,
//这个是标准未//定义的。 例如:1 int num = 10;

我们分别给出逻辑右移和算数右移:
逻辑右移
算数右移
总结:
移位操作符操作数只能是整数!不能是其它的数!

四,位操作符

位操作符有三种分别是: &(按位与) |(按位或) ^(按位异或)~(按位取反)。其中按位的位指的是二进制位。举个例子;

#include<stdio.h>
int main()
{int a = -3;int b = 6;int x = 0;int y = 0;int r = 0;int c = 0;x = a & b;y = a|b;r = a^b;c = ~a;printf("a&b = %d\n",x);printf("a|b = %d\n",y);printf("a^b = %d\n",r);printf("~a = %d\n",c);return 0;
}

在这里插入图片描述

紧接着我们来分析为什么是这个结果。大家请看图

在这里插入图片描述

在这里插入图片描述
通过图片已经能非常直观的能看清楚每一步的运算过程了。但有一点要注意就是按位操作符他们的操作数必须是整数。

学习完上面的知识后我们来看一道比较变态的面试题,题目是不创建第三变量怎样实现两个数的交换。这里我们不卖关子直接给出代码然后分析:

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

在这里插入图片描述
是不是很神奇,那为什么这样就能直接交换了呢?我们给出相应的图解;
在这里插入图片描述
紧接着我们扩展学习一些按位操作符的妙用。

1,&按位与的妙用

我们用一道编程题来举例,求⼀个整数存储在内存中的⼆进制中1的个数。(一下都以这道题为例)我们直接给出代码:

#include<stdio.h>
int main()
{int n = 0;scanf("%d",&n);int count = 0;while(n){if(n%2==1){count++;}n=n/2;}printf("count=%d",count);return 0;
}

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

15的二进制序列为00000000000000000000000000001111 写出其补码后发现有4个一这与结果是吻合的,但当我们输入负一结果就不对了显然这种方法有缺陷。我们给出改进方法:

#include<stdio.h>
int main()
{int n = 0;scanf("%d", &n);int count = 0;for (int i = 0;i < 32;i++){if (n&1==1){count++;}n = n >> i;}printf("count=%d", count);return 0;
}

在这里插入图片描述

这时候我们来看就会发现已经得到我们想要的结果了,按位与是不是非常的神奇呢我们来分析一下原理。
在这里插入图片描述
还有一个更加巧妙的方法,我们直接给出代码让你体会体会这种巧妙:

#include<stdio.h>
int main()
{int num = 0;scanf("%d", &num);int count = 0;while (num){num = num & (num - 1);count++;}printf("count=%d\n", count);return 0;
}

在这里插入图片描述
这段代码明显又要比上面的代码更加高效了,上面无论怎样都要执行32次循环,而下面这段代码有几个1就循环几次效率大幅提升。那为什么是这样呢?我们画个图分析一下;
在这里插入图片描述

2,|按位或的妙用

先来看一道题目,将13二进制序列的第5位修改为1,然后再改回0;
先画个图分析:
在这里插入图片描述
我们给出代码:

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

在这里插入图片描述
这里如果为什么变成了29还不知道的话那就要去看一下我之前的文章进制转换啦传送门:
那怎么换回来呢?其实也简单,我们画图来分析:

在这里插入图片描述
我们给出代码:

#include<stdio.h>
int main()
{int m = 13;int n = 5;m = m|(1 << (n - 1));printf("%d", m);m=m&~(1 << (n - 1));printf("%d",m);return 0;
}

在这里插入图片描述

由于文章篇幅有限以上就是本篇文章的所有内容啦,还有些内容将在下期发布敬请期待!

文章有点长感谢能够看到这里的读者,给你们点赞!如果这篇文章能够帮到你,制作不易还请各位读者给一个三连!你们的支持就是我最大的动力!
在这里插入图片描述


http://www.ppmy.cn/server/164586.html

相关文章

HarmonyOS应用开发快速入门

本节内容将帮助开发者学习如何构建一个全新的HarmonyOS应用&#xff0c;学习使用DevEco Studio创建新项目、使用预览器预览页面、了解基础组件如Image、Text等。 文章目录 一、介绍二、创建一个新项目三、页面结构总览四、自定义文本视图五、创建Image组件 一、介绍 根据本教程…

计算机网络 性能指标相关

目录 吞吐量 时延 时延带宽积 往返时延RTT 利用率 吞吐量 时延 时延带宽积 往返时延RTT 利用率

云计算部署模式全面解析

目录 引言公有云私有云混合云三种部署模式的对比选择建议未来趋势结语 1. 引言 随着云计算技术的快速发展,企业在选择云部署模式时面临着多种选择。本文将深入探讨云计算的三种主要部署模式:公有云、私有云和混合云,帮助读者全面了解它们的特点、优势及适用场景。 © iv…

Pyecharts之图表样式深度定制

在数据可视化的世界里&#xff0c;图表的样式定制对于提升数据展示效果和用户体验至关重要。Pyecharts 提供了丰富的样式定制功能&#xff0c;能让我们创建出独具特色的可视化作品。本篇将深入探讨如何使用 Pyecharts 为图表添加线性渐变色、径向渐变色&#xff0c;以及如何添加…

数据结构---哈希表

基本概念 哈希函数&#xff08;Hash Function&#xff09;是一种将输入的数据&#xff08;通常是任意大小的&#xff09;映射到固定大小的输出&#xff08;通常是一个固定长度的值&#xff09;的函数。这个输出值通常称为“哈希值”&#xff08;Hash Value&#xff09;或“哈希…

使用 KNN 搜索和 CLIP 嵌入构建多模态图像检索系统

作者&#xff1a;来自 Elastic James Gallagher 了解如何使用 Roboflow Inference 和 Elasticsearch 构建强大的语义图像搜索引擎。 在本指南中&#xff0c;我们将介绍如何使用 Elasticsearch 中的 KNN 聚类和使用计算机视觉推理服务器 Roboflow Inference 计算的 CLIP 嵌入构建…

【TypeScript】扩展:装饰器

文章目录 装饰器一、类装饰器1. 基本用法2. 装饰器返回值3. 构造类型4. 替换被装饰的类 二、装饰器工厂三、装饰器组合四、属性装饰器五、方法装饰器六、访问器装饰器七、参数装饰器 装饰器 装饰器本质是一种特殊函数&#xff0c;可以对类、属性、方法、参数进行扩展&#xff…

【贪心算法】在有盾牌的情况下能通过每轮伤害的最小值(亚马逊笔试题)

思路&#xff1a; 采用贪心算法&#xff0c;先计算出来所有的伤害值&#xff0c;然后再计算每轮在使用盾牌的情况下能减少伤害的最大值&#xff0c;最后用总的伤害值减去能减少的最大值就是最少的总伤害值 public static long getMinimumValue(List<Integer> power, int…