2.4 C语言之运算符

2.4 C语言之运算符

  • 一、算术运算符
  • 二、关系运算符
  • 三、逻辑运算符
  • 四、自增自减运算符
  • 五、按位运算符
  • 六、赋值运算符
  • 七、条件表达式
  • 八、运算符优先级与求值次序

一、算术运算符

二元算术运算符包括:+(加)、-(减)、*(乘)、/(除)、%(取模)

  • 整数除法会截断结果中的小数部分
  • 表达式x % y的结果是x除以y的余数,当x能被y整除时,其值为0。
  • 取模运算符不能应用于float和double类型。
  • 在有负操作数的情况下,整数除法截取的方向以及取模运算结果的符号取决于具体机器的实现,这和处理上溢和下溢的情况是一样的
  • 二元运算符+-具有相同的优先级,它们的优先级比*/%的优先级低
  • 而二元运算符*/%的优先级低于一元运算符+-
  • 算术运算符采用从左到右的结合规律

二、关系运算符

关系运算符包括:>>=<<=

  • 关系运算符优先级相同
  • 关系运算符优先级低于算术优先级,因此 i < lim - 1 等价于 i < (lim - 1)
  • 关系运算符优先级高于相等性运算符(==!=),因此0 != a <= 1 等价于 0 != (a <= 1)

三、逻辑运算符

逻辑运算符包括:&&(与) 、||(或) 、!(非)

  • &&||连接的表达式按从左到右的顺序进行求值,并且,在知道结果值为真或假后立即停止计算(短路)。
  • &&优先级高于||,但是两者都比关系运算符和相等性运算符的优先级低
  • 在关系表达式或逻辑表达式中,如果关系为真,则表达式的结果值为数值1,如果为假,则结果值为数值0
  • 逻辑运算符!的作用是将非0操作数转换为0,将操作数0转换为1。一般这样用 if(!valid),一般不采用 if(valid==0)

四、自增自减运算符

C语言提供了两个用于变量递增与递减的特殊运算符。自增运算符++使其操作数递增1,自减运算符--使其操作数递减1。

  • ++--这两个运算符特殊的地方在于:它们既可以用作前缀运算符(++n),也可以用作后缀运算符(n++)。在这两种情况下,其效果都是将变量n的值加1。但是,它们之间有一点不同。表达式++n先将n的值递增1,然后再使用变量n的值;而表达式n++则是先使用n的值,然后再将n的值递增1。
  • 如果n的值为5,那么 x = n++; 执行后的结果是将x置为5,而 x = ++n; 执行后的结果是将x置为6,这两条语句执行完成后,变量n的值都是6。
  • 自增自减运算符只能作用于变量,类似于表达式(i+j)++是非法的

五、按位运算符

C语言提供了6个位操作运算符。这些运算符只能作用于整型操作数,即只能作用于带符号或无符号char、short、int、long类型:

运算符说明运算规则
&按位与(AND)参与运算的两个二进位都为1,结果位才为1;1&1=1, 1&0=0,0&1=0,0&0=0
|按位或(OR)参与运算的两个二进位只要有一个为1,结果位就为1;1|1=1, 1|0=1, 0|1=1, 0|0=0
^按位异或(XOR)参与运算的两个二进位不同,结果位为1,相同,结果位为0;1^1=0, 1^0=1, 0^1=1, 0^0=0
<<左移m<<n,将二进制位左移n位
>>右移m>>n, 将二进制位右移n位
~按位求反(一元运算符)0变1,1变0
  • 按位与运算符&经常用于屏蔽某些二进制位(x&1=x; x&0=0,其中x取值0或者1),比如:
    n = n & 0177; 该语句将n中除7个低二进制位外的其它各位均置为0
    0177八进制–>十进制127–>二进制 01111111
    可以看出,0177对应的二进制的7个低位都是1,那么不管n的7个低位是1还是0,与0177进行&运算之后这7位的结果总是保持不变;而除了这7个低位,n的其它位都将&0,其结果显然也是0
  • 按位或运算符|经常用于将某些二进制位置为1(x|1=1; x&0=x,其中x取值0或者1),比如:
    n = n | SET_ON; 该语句将n中对应于SET_ON中为1的那些二进制位置为1。
  • 按位异或运算符^当两个操作数的对应位不相同时,将该位设置为1,否则,将该位设置为0
  • 注意区分按位运算符&| 与逻辑运算符&&||,比如:
    int x = 1, y = 2;
    printf(“%d”, x & y); // 0
    printf(“%d”, x && y); // 1
  • 移位运算符<<和>>分别用于将运算的左操作数左移和右移,移动的位数则由右操作数指定(右操作数的值必须是非负值)。表达式x<<2表示将x的值左移两位,右边空出的两位用0填补,该表达式等价于对左操作数乘以4;在对unsigned类型的值右移时,左边空出的部分用0填补;在对signed类型的值右移时,某些机器将对左边空出部分用符号位填补(即算术移位),而另一些机器则对左边空出部分用0填补(即逻辑移位)
#include <stdio.h>main()
{int x = 5; // 0000 0101 printf("%d\n", x << 2); // 0001 0100 20=x*4printf("%d\n", x >> 2); // 0000 0001 1=x/4unsigned int y = 5; // 0000 0101 printf("%d\n", y >> 2); // 0000 0001 1=x/4signed int z = -5; // 1000 0101原码 --> 1111 1010 反码(原码取反) --> 1111 1011 补码(反码加1)printf("%d\n", z >> 2); // 1111 1011(-5补码) -->右移2位,左边空位补符号位 1111 1110补码 --> 1111 1101反码 --> 1000 0010原码 -2return 0;
}

关于负数的二进制可以参考我的另一篇博客:负数的二进制

  • 一元运算符~用于求整数的二进制反码,即1变0,0变1,比如:
	int a = 64 + 16 + 1;// 077八进制-->十进制63-->二进制 011 1111 -->取反 0100 0000// 0101 0001  a//&0100 0000  ~077//=0100 0000a = a & ~077; // 将把a的最后六位设置为0printf("%d\n", a); 
  • 看一个例子
	printf("%d\n", ~0); // -1  1000 0001 -> 1111 1111(补)printf("%d\n", ~0 << 2); // 1111 1111(补) << 2 --> 1111 1100(补) 1111 1011(反) 1000 0100(原) -4printf("%d\n", ~(~0 << 2)); // 1111 1100 -->取反 0000 0011printf("%d\n", getbits(13, 2, 2));// 返回整数x从第p位(从右边数,假定最右边是第0位)开始,往右数n位的值,也即除了这n位,其左边位都置0
unsigned getbits(unsigned int x, int p, int n) {// 0000 1101 x=13 p=2 n=2// 0000 0110 //&0000 0011 // 0000 0010 2return (x >> (p + 1 - n)) & ~(~0 << n);
}

x >> (p + 1 - n) 将要求的n位数移到最右端,其中p+1-n就是要求的n位数的右端的没用的位数;
~0所有位都为1;
~0<<n左移n位,右端的n位置0;
~(~0<<n)右端的n位置1;
做&运算,将n位左边位都置0

六、赋值运算符

在赋值表达式中,如果表达式左边的变量重复出现在表达式的右边,如:
i = i + 2,
则可以将这种表达式缩写为下列形式:
i += 2,其中的+=属于赋值运算符
大多数二元运算符都有相应的赋值运算符op=,其中op可以是下面这些运算符之一:
+ - * / & << >> & ^ |

七、条件表达式

下面这组语句:

	if (a > b)z = a;elsez = b;

用于求a和b中的最大值,并将结果保存到z中。条件表达式(使用三元运算符" ? : ")提供了另外一种方法编写这段程序及类似的代码段。在表达式
expr1 ? expr2 : expr3
中,首先计算expr1,如果其值不等于0(为真),则计算expr2的值,并以该值作为条件表达式的值,否则计算expr3的值,并以该值作为条件表达式的值。expr2和expr3中只能有一个表达式被计算。因此,以上语句可以改写为:
z = (a>b) ? a : b; /* z = max(a,b) */

八、运算符优先级与求值次序

下表总结了所有运算符的优先级与结合性,同一行中的各运算符具有相同的优先级,各行间从上往下优先级逐行降低。

运算符结合性
() [ ] -> .从左至右
! ~ ++ – + - * (type) sizeof从右至左
* / %从左至右
+ -从左至右
<< >>从左至右
< <= > >=从左至右
== !=从左至右
&从左至右
^从左至右
|从左至右
&&从左至右
||从左至右
? :从左至右
= += -= *= /= %= &= ^= |= <<= >>=从右至左
,从左至右
  • 运算符-> .用于访问结构成员,sizeof 对象长度,后续讨论
  • 一元运算符*(通过指针间接访问),一元运算符&(对象地址),后续讨论
  • 注意:一元运算符+、-、*、&优先级高于二元运算符+、-、*、&
  • C语言没有指定同一运算符中多个操作数的计算顺序(&& || ?: ,运算符除外)。例如:
    x = f() + g();
    在上面的语句中,f()可以在g()之后计算,也可以在g()之前计算。因此,如果f或g改变了另一个函数所使用的变量,那么x的结果可能会依赖这两个函数的计算顺序。解决办法是把中间结果保存在临时变量中。
  • 类似地,C语言也没有指定函数各参数的求值顺序。例如:
    printf(“%d %d\n”, ++n, power(2, n)); 在不同的编译器中的输出结果可能不同,这取决于先执行n的自增还是先执行power函数,解决的办法是
    ++n;
    printf(“%d %d\n”, n, power(2, n));
  • 函数调用、嵌套赋值语句、自增、自减都可能产生副作用(在对表达式求值的同时,修改了某些变量的值)。在有副作用影响的表达式中,其执行结果同表达式中的变量被修改的顺序之间存在着微妙的依赖关系,比如:
    a[i] = i++;
    数组下标i是引用旧值还是新值?编译器不同,结果可能不同。C语言标准对大多数这类问题有意未作具体规定。表达式何时会产生这种副作用(对变量赋值),将由编译器决定,因为最佳的求值顺序同机器结构有很大关系。(ANSI C标准明确规定了所有对参数的副作用都必须在函数调用之前生效,但这对前面介绍的那种printf函数调用没有什么帮助)
  • 在任何一种编程语言中,如果代码的执行结果与求值顺序有关,则都是不好的程序设计风格。如果不知道这些问题在各种机器上是如何解决的,就不要尝试使用某种特殊的实现方式。

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

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

相关文章

扬声器(喇叭)

扬声器(喇叭) 电子元器件百科 文章目录 扬声器(喇叭)前言一、扬声器(喇叭)是什么二、扬声器(喇叭)的类别三、扬声器(喇叭)的应用场景四、扬声器(喇叭)的作用原理总结前言 扬声器广泛应用于音响系统、公共广播系统、汽车音响、电视、电脑和移动设备等各种电子设备…

Linux基本开发工具

编译器和自动化构建工具 一、编译器——gcc、g1. 安装 gcc/g2. 使用3. 链接库4. 拓展命令&#xff1a;od/file/ldd/readelf 二、自动化构建项目——make、makefile1. 介绍2. 使用例子touch——change file timestampsstat——display file or file system status修改时间 .PHON…

Qt 文字描边(基础篇)

项目中有时需要文字描边的功能 1.基础的绘制文字 使用drawtext处理 void MainWindow::paintEvent(QPaintEvent *event) {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing, true);painter.setRenderHint(QPainter::SmoothPixmapTransform, true);painte…

ceph的osd盘删除操作和iscsi扩展

ceph的osd盘删除操作 拓展:osd磁盘的删除(这里以删除node1上的osd.0磁盘为例) 1, 查看osd磁盘状态 [rootnode1 ceph]# ceph osd tree ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF -1 0.00298 root default -3 0.00099 host node10 hdd 0.00…

【Vins轨迹】pose_graph位姿图加载EVO精度评定

1. Vins的位姿图加载功能 如果想要对slam运行后的位姿轨迹进行评定&#xff0c;需要将数据保存到output文件夹中。 其中pose_graph.txt含有的信息&#xff1a;关键帧id、时间戳、vio的xyz、优化后的xyz、vio的四元数、优化后的四元数、回环到的关键帧id、回环信息&#xff08…

【Py/Java/C++三种语言OD2023C卷真题】20天拿下华为OD笔试【DP】2023C-分班【欧弟算法】全网注释最详细分类最全的华为OD真题题解

文章目录 题目描述与示例题目描述输入描述输出描述示例一输入输出 示例二输入输出 解题思路代码PythonJavaC时空复杂度 华为OD算法/大厂面试高频题算法练习冲刺训练 题目描述与示例 题目描述 幼儿园两个班的小朋友在排队时混在了一起&#xff0c;每位小朋友都知道自己是否与前…

【十】python复合模式

10.1 复合模式简介 在前面的栏目中我们了解了各种设计模式。正如我们所看到的&#xff0c;设计模式可分为三大类:结构型、创建型和行为型设计模式。同时&#xff0c;我们还给出了每种类型的相应示例。然而&#xff0c;在软件实现中&#xff0c;模式并是不孤立地工作的。对于所…

HPM5300系列--第一篇 命令行开发调试环境搭建

一、目的 在之前的博客中《HPM6750系列--第二篇 搭建Ubuntu开发环境》、 《HPM6750系列--第三篇 搭建MACOS编译和调试环境》我们介绍了HPM6750evkmini开发环境的搭建过程&#xff0c;由于HPM5300系列共用一套hpm-sdk&#xff0c;故HPM5300的开发调试环境的搭建过程基本和之前的…

golang学习笔记——互斥锁sync.Mutex、计数器sync.WaitGroup、读写锁sync.RWMutex

文章目录 互斥锁&#xff1a; sync.Mutexsync.WaitGroup 计数器例子func (*WaitGroup) Addfunc (*WaitGroup) Donefunc (*WaitGroup) Wait 读写互斥锁参考资料 临界区总是需要通过同步机制进行保护的&#xff0c;否则就会产生竞态条件&#xff0c;导致数据不一致。 互斥锁&…

智能故障诊断期刊推荐【中文期刊】

控制与决策 http://kzyjc.alljournals.cn/kzyjc/home 兵工学报 http://www.co-journal.com/CN/1000-1093/home.shtml 计算机集成制造系统 http://jsjjc.soripan.net/ 机械工程学报 http://www.cjmenet.com.cn/CN/0577-6686/home.shtml 太阳能学报 https://www.tynxb.org.c…

Visual Studio Code中的任务配置文件tasks.json中的可选任务组tasks详解

☞ ░ 前往老猿Python博客 ░ https://blog.csdn.net/LaoYuanPython 一、引言 vscode是支持通过配置可以实现类似Visual C等IDE开发工具使用菜单和快捷键直接进行程序编译构建的&#xff0c;这样构建的任务可以结合后续的调试配置进行IDE环境的程序调试&#xff0c;不过在之前…

12. IO

1.File类 • File 类代表与平台无关的文件和目录。 • File 能新建、删除、重命名文件和目录&#xff0c;但 File 不能访问文件内容本身。如果需要访问文件内容本身&#xff0c;则需要使用输入/输出流。 1).File的常用方法 在这里插入图片描述 2).遍历给定目录所有文件 …

Android源码下载流程

1.使用repo方式&#xff1a; https://github.com/jeanboydev/Android-ReadTheFuckingSourceCode/blob/master/article/android/framework/Android-Windows%E7%8E%AF%E5%A2%83%E4%B8%8B%E8%BD%BD%E6%BA%90%E7%A0%81.md 2.使用git方式&#xff1a; Windows 环境下载 Android 源…

QT之QMatrix

QT之QMatrix 成员函数介绍使用注意函数的使用 成员函数介绍 reset()&#xff1a;将矩阵重置为单位矩阵&#xff08;无变换&#xff09;。 translate()&#xff1a;执行平移变换。例如&#xff0c;translate(qreal dx, qreal dy)将图形沿x轴和y轴方向分别平移dx和dy个单位。 sc…

MySQL增删改查

查询数据 MySQL 数据库使用 SQL SELECT 语句来查询数据。以下为在 MySQL 数据库中查询数据通用的 SELECT 语法&#xff1a; SELECT column_name,column_name FROM table_name [WHERE Clause] [LIMIT N][ OFFSET M] 查询语句中你可以使用一个或者多个表&#xff0c;表之间使用…

联想笔记本如何安装Vmware ESXi

环境&#xff1a; Vmware ESXi 8.0 Vmware ESXi 6.7 联想E14笔记本 问题描述&#xff1a; 联想笔记本如何安装Vmware ESXi 解决方案&#xff1a; 1.官网下载镜像文件 https://customerconnect.vmware.com/en/downloads/search?queryesxi%208 下载 2.没有账户注册一个 …

什么时候使用匿名类,匿名类解决了什么问题?为什么需要匿名类 ?

匿名类通常在以下场景下使用&#xff1a; 一次性使用&#xff1a; 当你需要创建一个类的实例&#xff0c;但该类只在一个地方使用&#xff0c;而不打算在其他地方重复使用时&#xff0c;可以考虑使用匿名类。 简化代码&#xff1a; 当创建一个小型的、一次性的类会让代码更简洁…

浅析特征增强个性化在CTR预估中的经典方法和效果对比

在CTR预估中&#xff0c;主流都采用特征embeddingMLP的方式&#xff0c;其中特征非常关键。然而对于相同的特征&#xff0c;在不同的样本中&#xff0c;表征是相同的&#xff0c;这种方式输入到下游模型&#xff0c;会限制模型的表达能力。为了解决这个问题&#xff0c;CTR预估…

12.14 log 376. 摆动序列,53. 最大子序和

376. 摆动序列 class Solution { public:int wiggleMaxLength(vector<int>& nums) {if(nums.size()1) return nums.size();int preDiff0;int curDiff0;int result1;for(int i0;i<nums.size()-1;i){curDiffnums[i1]-nums[i];if(preDiff<0&&curDiff>…

【每日一题】用邮票贴满网格图

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;二维前缀和二维差分 写在最后 Tag 【二维前缀和】【二维差分】【矩阵】【2023-12-14】 题目来源 2132. 用邮票贴满网格图 题目解读 在 01 矩阵中&#xff0c;判断是否可以用给定尺寸的邮票将所有 0 位置都覆盖住&…