# 深入解析C/C++中的关键运算符:i++, ++i, a=i++, a=++i 及复杂表达式的运算顺序

原因

  • 有没有人跟我一样,根本记不住那么多的运算符优先级,凭感觉猜的运算
    顺序,导致代码出错,调试半天,最后发现是优先级的问题
  • 有没有跟我一样,看到复杂表达式就头大
  • 看到一些复杂的表达式,不知道怎么去分析,只能硬着头皮去写,然后运行看结果,有时候还不懂为啥是那样运行的
  • 痛定思痛,决定写一篇博客,总结一下,以后再遇到复杂的表达式,可以更新上去,参考这篇博客,加深理解

前言

在C/C++编程中,运算符的优先级和结合性是理解复杂表达式运算顺序的关键。本文将深入探讨i++++ia=i++a=++i这四个关键运算符的运算顺序,并分析它们在不同情况下的行为。如果绝对对您有所帮助,请可以点个关注收藏一下,谢谢!
墨小羽ovo

1.运算符优先级和结和性

1.1 算数运算符

  • +-*/%:算术运算符,按照从左到右的顺序进行运算。
  • ++--:自增和自减运算符,按照从右到左的顺序进行运算。

1.2 赋值运算符

  • =:赋值运算符,按照从右到左的顺序进行运算。

1.3 关系运算符

  • ==!=<><=>=:关系运算符,按照从左到右的顺序进行运算。

1.4 逻辑运算符

  • &&||:逻辑运算符,按照从左到右的顺序进行运算。

1.5 位运算符

  • &|^~<<>>:位运算符,按照从左到右的顺序进行运算。
    示例程序:
#include <stdio.h>
int main() {
    int a = 1, b = 2, c = 3;
    int d = a + b<<1
    printf("d = %d\n", d); // 输出:d = 5
    return 0;
}

输出结果:

d = 6

注意 可能好多人以为等于5,我也这样以为哩,看了好久没想明白

  • <<运算符的优先级低于+运算符,所以先进行+运算,再进行<<运算。
  • 运算顺序:先算a+b,再算<<1,最后赋值给d。

1.6 条件运算符(三元运算符)

  • ?::条件运算符,按照从右到左的顺序进行运算。
    示例:
int a = 1, b = 2, c = 3;
int d = a > b ? a : b; // 等价于 int d = (a > b) ? a : b;
`d = 2`

1.7 指针运算符

  • *&:指针运算符,按照从右到左的顺序进行运算。

1.8 sizeof运算符

  • sizeof:sizeof运算符,按照从右到左的顺序进行运算。

结合方向

  • 从右到左:双目运算符中的赋值运算符 单目运算符,三目运算符
  • 从左到右:算数运算符,关系运算符,逻辑运算符,位运算符
  • 优先级:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符

运算符结合的优先级表

参考这位大佬的博客,很详细

运算符结合优先级表

2. i++++i

  • i++:后置递增运算符,先返回i的当前值,然后将i的值增加1。
  • ++i:前置递增运算符,先将i的值增加1,然后返回增加后的值。

示例程序

#include <stdio.h>

int main() {
    int i = 0;
    int a = i++;
    printf("i = %d, a = %d\n", i, a); // 输出:i = 1, a = 0

    i = 0;
    a = ++i;
    printf("i = %d, a = %d\n", i, a); // 输出:i = 1, a = 1

    return 0;
}

3. a=i++a=++i

  • a=i++:先将i的当前值赋给a,然后将i的值增加1。
  • a=++i:先将i的值增加1,然后将增加后的值赋给a
    示例程序
#include <stdio.h>

int main() {
    int i = 0;
    int a = i++;
    printf("i = %d, a = %d\n", i, a); // 输出:i = 1, a = 0

    i = 0;
    a = ++i;
    printf("i = %d, a = %d\n", i, a); // 输出:i = 1, a = 1

    return 0;
}

4.*(pDataByte++)*pDataByte++区别

  • *(pDataByte++):先解引用pDataByte指向的地址,然后将pDataByte的值增加1。
  • *pDataByte++:先将pDataByte的值增加1,然后解引用增加后的地址。
    示例程序
#include <stdio.h>

int main() {
    int data[] = {1, 2, 3};
    int *pDataByte = data;
    # if 1
    // int a = *(pDataByte++);
    printf("a = %d\n",*(pDataByte++)); // 输出:a = 1
    #else
    //int b = *pDataByte++;
    printf("b = %d\n", *pDataByte++); // 输出:b = 1
   #endif
    return 0;
}

运行结果:

a = 1 b = 1

5.USART_RX_BUF[USART_RX_LEN++]=Res;

  • USART_RX_BUF[USART_RX_LEN++]=Res:先将Res的值赋给USART_RX_BUF[USART_RX_LEN],然后将USART_RX_LEN的值增加1。
    示例程序
#include <stdio.h>

int main() {
    char USART_RX_BUF[10] = {0};
    int USART_RX_LEN = 0;
    char Res = 'A';
    USART_RX_BUF[USART_RX_LEN++] = Res;
    printf("USART_RX_BUF[%d] = %c\n", USART_RX_LEN - 1, USART_RX_BUF[USART_RX_LEN - 1]); // 输出:USART_RX_BUF[0] = A

    return 0;
}

输出结果:

USART_RX_BUF[0] = A

a+++b

  • a+++b:先返回a的当前值,然后将a的值增加1,最后返回b的值。
  • 执行顺序:先执行a++,所以a等于0,在执行a+b再执行b,最后返回a的当前值。

示例程序

#include <stdio.h>

int main() {
    int a = 0;
    int b = 1;
    int c = a+++b;
    printf("a = %d, b = %d, c = %d\n", a, b, c); // 输出:a = 1, b = 1, c = 1

    return 0;
}

输出结果:

a = 1, b = 1, c = 1

a++,(a++) (*a)++ *++a,

  • a++和(a++)都返回a原来指向的值,并将a指向下一个内存位置。
  • (*a)++返回a指向的值,并将该值增加1,但不影响a的指向。
  • *++a先将a指向下一个内存位置,然后返回新位置的值。

示例程序

#include <stdio.h>

int main() {
    int data[] =
    { 1, 4, 7 };
    int *a = data;
    //printf("%d\n", *a++); // 输出:1
    // printf("%d\n", *(a++)); // 输出:1
    // printf("%d\n", (*a)++); // 输出:1
    // printf("%d\n", *++a); // 输出:4
     printf("%d\n", ++*a); // 输出:2

    return 0;
}

参考资料

运算符结合优先级表
C语言基础知识:操作符详解(附操作符优先级及结合性一览表

总结

这篇博客,主要介绍了C语言中的运算符,包括算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符、条件运算符、指针运算符、sizeof运算符,以及一些复杂运算符的使用示例。后续遇到了,会继续补充。最后呢,在编写博客的过程中,我尽量保持内容的准确性和完整性,但也难免会有疏漏或错误之处。欢迎各位读者指出其中的问题,帮助我不断进步。谢谢大家的阅读,祝大家学习愉快!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数字身份管理发展趋势:​​​​​​扩展身份安全能力

身份作为企业各个应用的入口&#xff0c;大量存在于企业的内部业务和外部业务中&#xff0c;身份作为最核心数据对于企业的重要性不言而喻&#xff0c;因此也往往成为攻击者的攻击目标&#xff0c;从2023年国资国企受攻击的情况也不难看出&#xff0c;针对身份的攻击累计超过37…

metersphere链接腾讯邮箱步骤

1、打开腾讯邮箱生成授权码 路径&#xff1a;设置-账户-账户安全 生成的授权码只会展示1次&#xff0c;注意保存 2、在系统设置-系统参数设置-邮件设置填写授权码和SMTP信息 SMTP信息在邮箱的客户端设置中可以获取到对应的信息 3、信息填写完后&#xff0c;可以测试连接&…

golang 项目打包部署环境变量设置

最近将 golang 项目打包部署在不同环境&#xff0c;总结一下自己的心得体会&#xff0c;供大家参考。 1、首先要明确自己目标服务器的系统类型(例如 windows 或者Linux) &#xff0c;如果是Linux 还需要注意目标服务器的CPU架构(amd或者arm) 目标服务器的CPU架构可执行命令&…

Modbus通信协议学习——调试软件

Modbus通信协议是一种广泛应用于工业自动化领域的串行通信协议&#xff0c;由Modicon公司&#xff08;现为施耐德电气Schneider Electric&#xff09;于1979年开发。该协议已成为工业电子设备之间通信的通用标准&#xff0c;支持多种设备和系统之间的数据交换。以下是对Modbus通…

值传递与引用传递:深入理解Java中的变量赋值和参数传递机制

在Java中&#xff0c;理解值传递&#xff08;值拷贝&#xff09;与引用传递&#xff08;地址拷贝&#xff09;之间的区别对于正确处理数据结构和对象至关重要。本文将通过示例代码深入探讨这两种机制&#xff0c;并解释它们如何影响程序的行为。 值传递&#xff08;值拷贝&…

第16章 主成分分析:四个案例及课后习题

1.假设 x x x为 m m m 维随机变量&#xff0c;其均值为 μ \mu μ&#xff0c;协方差矩阵为 Σ \Sigma Σ。 考虑由 m m m维随机变量 x x x到 m m m维随机变量 y y y的线性变换 y i α i T x ∑ k 1 m α k i x k , i 1 , 2 , ⋯ , m y _ { i } \alpha _ { i } ^ { T } …

Drools开源业务规则引擎(二)- Drools规则语言(DRL)

文章目录 1.DRL文件的组成&#xff1a;2.package3.import4.function5.query6.declare7.global8.rule8.1.规则属性8.2.LHS8.2.1.语法格式8.2.2.运算符优先级8.2.3.特殊的运算符1.matches, not matches2.contains, not contains3.memberOf, not memberOf4.in, notin5.soundslike6…

7.8作业

一、思维导图 二、 1】按值修改 2】按值查找&#xff0c;返回当前节点的地址 &#xff08;先不考虑重复&#xff0c;如果有重复&#xff0c;返回第一个&#xff09; 3】反转 4】销毁链表 //按值修改 int value_change(linklistptr H,datatype e,int value) {if(HNULL||empty(H…

推出PSoC™ 车规级4100S Max系列,(CY8C4147LDE 和 CY8C4147LDS)支持性能更强大的第五代CAPSENSE™技术

推出全新车规级PSoC™ 4100S Max系列。这一微控制器器件系列具有更佳的闪存密度、通用输入输出接口&#xff08;GPIO&#xff09;、CAN-FD和硬件安全性&#xff0c;扩展了采用CAPSENSE™技术的汽车车身/暖通空调&#xff08;HVAC&#xff09;和方向盘应用人机界面&#xff08;H…

Unity之Text组件换行\n没有实现+动态中英互换

前因:文本中的换行 \n没有换行而是打印出来了,解决方式 因为unity会默认把\n替换成\\n 面板中使用富文本这个选项啊 没有用 m_text.text = m_text.text.Replace("\\n", "\n"); ###动态中英文互译 using System.Collections; using System.Collections…

什么叫低频晶振?低频晶振最低频率能达到多少?低频晶振封装尺寸有哪些?

低频晶振指的是那些工作在较低频率范围内的晶体振荡器&#xff0c;通常这类振荡器的标称频率低于8MHz。这些晶振在各种电子设备中都有应用&#xff0c;尤其是在那些需要精确但不需要高频振荡的应用场景中&#xff0c;比如实时时钟(RTC)、低速串行通信接口(如UART、IC等)、以及一…

怎么才能选到好的猫咪主食冻干?公认顶尖优秀主食冻干总结

如今&#xff0c;主食冻干市场纷繁多样&#xff0c;质量水平却大相径庭。部分品牌盲目追求高营养值和利润增长&#xff0c;却忽略了猫咪健康饮食的本质需求&#xff0c;导致市场上充斥着以次充好、虚假标注日期等不法行为。更有甚者&#xff0c;部分产品未经权威第三方检测便匆…

提高LabVIEW软件的健壮性

提高LabVIEW软件的健壮性&#xff0c;即增强其在各种操作条件下的可靠性和稳定性&#xff0c;是开发过程中非常重要的一环。健壮的软件能够在面对意外输入、极端环境和系统故障时依然表现出色&#xff0c;确保系统的连续性和可靠性。以下是详细的方法和策略&#xff0c;从多个角…

【活动行】参与上海两场线下活动,教育生态行业赛总决赛活动和WAIC人工智能大会活动 - 上海活动总结

目录 背景决赛最后一公里领域范围 决赛作品AI智教相机辅导老师Copilot辅导老师Copilot雅思写作竞技场 优秀作品总结 背景 决赛 百度发起的千帆杯教育生态行业赛于2024年7月4日进行线下决赛&#xff0c;博主虽然没能进入决赛&#xff0c;但也非常荣幸能够以嘉宾身份到现场给进…

Leaflet【七】加载海量点数据

本文深入探讨了Leaflet在渲染海量点数据时面临的性能挑战&#xff0c;提出了一种创新的解决方案——利用leaflet-marker-canvas插件。传统的循环绘制Marker方式在数据量巨大时会导致明显的性能下降&#xff0c;而通过将点数据加入Canvas进行批量渲染&#xff0c;显著提高了绘图…

vite+vue3拍照上传到nodejs服务器

一:效果展示: 拍照效果 二:Nodejs后端接口代码: 三:前端完整代码:

【productj服务导出文件503问题】

设备服务只要导出文件&#xff0c;就报503&#xff0c;查看K8S发现服务重启 1. 复现问题1.1 问题复现频繁fullGC 宿主pod服务日志监控1.2 小内存复现 接口没啥问题&#xff0c;导出就会导致服务重启 1. 复现问题 当前uat环境配置&#xff1a; pod内存&#xff1a;2G JVM参数&a…

C++入门(C语言过渡)

文章目录 前言一、C关键字二、命名空间三、C输入&输出四、缺省参数五、函数重载六、引用七、inline八、nullptr总结 前言 C是一种通用的、高级的、静态类型的编程语言&#xff0c;它在20世纪80年代由丹尼斯里奇创建的C语言基础上发展而来。以下是C发展的一些重要里程碑。 1…

【目录】阅读须知!全博文、专栏大纲

首先要和大家说一下&#xff0c;博主的文章并不是想到哪里写到哪里&#xff0c;而是以整个大后端为主题&#xff0c;成体系的在写专栏&#xff0c;从和后端紧相关的计算机核心课程开始、到JAVA SE、JAVA EE、到数据库、MQ等各类中间件、再到业务场景、性能优化。当然也会涉及一…

Docker拉取失败,利用github将镜像推送到阿里云

背景 由于近期国内docker镜像地址失效&#xff08;2024年6月份开始&#xff09;&#xff0c;导致pull docker 镜像总是超时。 涉及到的网址和工具 https://github.com/tech-shrimp/docker_image_pusherhttps://hub.docker.com/search阿里云 GITHUB配置 fork https://githu…