c++高级---c语言中关于运算符优先级和运算符集合顺序的理解(*p++和*++p的区别)

*p++操作执行的过程 在项目中遇见了 *p++ 这种操作,但不明白在 *p++中 ++ 和 * 是怎样执行的?现在我们来一一剖析它的运算过程。 C语言中取值运算符 * 与前置自增运算符++、后置自增运算符++都属于单目运算符,运算符的优先级顺序同为第2级,结合方向为 右到左。其中,* 使用形式为:*p,用于指针变量,前置自增使用形式为 ++i,后置自增使用形式为 ++i。 注意 同一优先级的运算符,运算次序由结合方向所决定。 简单记就是:! > 算术运算符 > 关系运算符 > && & 阅读详情

转自:http://blog.youkuaiyun.com/zhang429350061/article/details/8775693

接下来,通过示例彻底理解自增运算符的两种用法(自减的用法与之类似,只不过是加1变成了减1)。

    1、++i和i++的区别

    如清单1(注意代码中的注释): 

[cpp]  view plain copy
  1. #include <stdio.h>  
  2.   
  3. int main(void)  
  4. {  
  5.     int a, b, i = 7;  
  6.   
  7.     i++; //等价于i = i + 1;  
  8.     ++i; //等价于i = i + 1;  
  9.   
  10.     a = i++; //等价于a = i; i = i + 1;  
  11.     b = ++i; //等价于i = i + 1; b = i;  
  12.       
  13.     printf("a = %d, b = %d\n", a, b);  
  14.       
  15.     return 0;  
  16. }  

    例子输出结果: 

[cpp]  view plain copy
  1. a = 9, b = 11  

    在例子中,第7和第8行的作用一样,仅仅是为变量i加1,这时i的值已经增加为9,接下来第10行变量a先获得i的值(即9),然后i加1,第11行变量i先再加1,然后把得到的值赋给b,所以b的值为11。

    稍微复杂的例子,如清单2: 

[cpp]  view plain copy
  1. #include <stdio.h>  
  2.   
  3. int main(void)  
  4. {  
  5.     int a = 5;  
  6.   
  7.     int *p = &a;  
  8.   
  9.     int b = (*p)++; //等价于b = a++; 即b = a; a = a + 1;  
  10.   
  11.     int c = ++(*p); //等价于c = ++a; 即a = a + 1; c = a;   
  12.       
  13.     printf("b = %d, c = %d\n", b, c);  
  14.   
  15.     printf("(*p)++ = %d, ++(*p) = %d\n", (*p)++, ++(*p));  
  16.   
  17.     return 0;  
  18. }  

    例子输出结果: 

[cpp]  view plain copy
  1. b = 5, c = 7  
  2. (*p)++ = 8, ++(*p) = 8  

    在这个例子中,只不过是通过*p来间接地操作a,其他关于自增运算符的用法与清单1类似。第9行的*p一定要用小括号括起来,否则含义就不一样了。而第11行的++(*p)也可以写成++*p(用GCC验证过),那是因为对操作数p来说它只有一个运算符*在计算它,所以无关乎运算符优先级和结合性的问题。

    值得注意的是,由于C语言没有指定函数各参数的求值顺序,所以第15行的代码是不可移植的,用不同的编译器可能会产生不同的结果(对于这个例子,GCC是先计算++(*p),后计算(*p)++,所以两者都等于8)。

    知识点:

    (1)、副作用

    在对表达式求值的同时,修改了某些变量的值,其中修改值的行为在C语言中被叫作副作用,那是因为对C语言而言,计算的目的就是对表达式求值,如语句int a = 5,它的含义是先求值得到5,然后把5赋值给变量a,后一步的赋值就是此表达式的副作用。自增和自减运算符就是因为副作用而被使用,除了加1或减1之外,还给自身赋值。

    (2)、运算符的优先级

    在C语言中,把运算符的优先级分为15级,如下表,从上到下,依次为从最高优先级到最低优先级(为了方便记忆,将15级分成11类,并对每类进行了命名)。

初等运算符

包括小括号 ()、中括号 [] 、成员访问运算符 . 和 -> 。

一元运算符

包括自增++和自减--、正负号+ 和-、间接运算*和取址运算& 、类型转换(type)、 sizeof 、逻辑反! 、位取反~等。

算术运算符

包括两级,先乘除(*、/、%)后加减(+、-)。

位移运算符

包括左移 << 和右移 >> 。

关系运算符

包括小于 < 、小于等于 <= 、大于 > 、大于等于 >= 。

判等运算符

包括相等 == 和不相等 != 。

位逻辑运算符

分三级,依次为位与 &、位异或 ^ 和位或 | 。

逻辑运算符

分两级,依次为逻辑与 && 和逻辑或 || 。

条件运算符

? :

赋值运算符

包括= 、+= 、-=、 *=、 /=、 %= 、&= 、^=、 |= 、<<= 、>>= 。

逗号运算符

,

    (3)、结合性

    对于同一操作数,在具有两个相同优先级的操作符时决定先执行哪个操作符的问题就是由结合性决定的。

    相同优先级的操作符具有同样的结合性。右结合性就是说表达式中最右边的操作最先执行,然后从右到左依次执行。在C语言中,具有右结合性的操作符只有相应的三类,分别为一元运算符、条件运算符和赋值运算符。

    注意:C语言中的优先级和结合性都是针对同一操作数而言的。如表达式24/8*2,对于操作数8而言,/ 和*的优先级相同,所以再根据它们的左结合性可知,表达式是先计算24/8得到3,然后计算3*2得到6。

    C语言并没有规定同一运算符相关的多个操作数的计算顺序(&&、|| 、? : 和 , 运算符除外),如式子a = 8 * 9 + 20 * 4,对操作数9和20而言,根据优先级就可判断先乘后加,但表达式中的两个*并不共享同一操作数,所以从左到右的结合性并不适用它,8 * 9 和20 * 4的计算顺序是不定的,到底先计算8 * 9还是20 * 4由编译器决定。

    在上面例子中,8 * 9和20 * 4谁先执行都不影响最后结果的一致,但有些情况下就未必了,如“ b = 3; a = (b++) * (b++); ”这样的例子,对于不同的编译器最后a的值可能等于9,也可能等于12,甚至可能等于16。因此,在实际应用中不能出现这样的未确定性,根据自己的需要,可以把它改成类似“b = 3; c = b++; a = c * c;”这样的形式。

    2、*p++和*++p的区别

    举例,如清单3: 

[cpp]  view plain copy
  1. #include <stdio.h>  
  2.   
  3. int main(void)  
  4. {  
  5.     int arr[] = {1, 2, 3, 4};  
  6.     int *p = arr;  
  7.   
  8.     int a = *p++; //等价于a = *(p++); 即a = *p; p = p + 1;  
  9.       
  10.     int b = *++p; //等价于b = *(++p); 即p = p + 1; b = *p;  
  11.       
  12.     printf("a = %d, b = %d\n", a, b);  
  13.   
  14.     return 0;  
  15. }  

    例子输出结果: 

[cpp]  view plain copy
  1. a = 1, b = 3  

    对于第8行的操作数p而言,*和++的优先级相同,但根据它们的右结合性可知,在这个表达式里可认为++的优先级高于*,即*p++等价于*(p++)。

    而对于第10行的操作数p而言,它只有一个运算符++,所以先计算++p得出结果,然后间接运算。

【其实对于*p++到底是等价于*p,p++还是p++,*p,可能不同编译器设计的不同,但其结果都一样,不用太纠结,按照上面的理解就行。最主要要记住p++整个表达式返回的是p,然后稍过一段时间即整个语句也即大部分情况下碰到分号“;”后p才++】

 

 

最后,附一个更清晰详细的运算符优先级的表:

优先级

运算符

名称或含义

使用形式

结合方向

说明

1

[]

数组下标

数组名[常量表达式]

左到右

 

()

圆括号

(表达式)/函数名(形参表)

 

.

成员选择(对象)

对象.成员名

 

->

成员选择(指针)

对象指针->成员名

 

2

-

负号运算符

-表达式

右到左

单目运算符

(类型)

强制类型转换

(数据类型)表达式

 

++

自增运算符

++变量名/变量名++

单目运算符

--

自减运算符

--变量名/变量名--

单目运算符

*

取值运算符

*指针变量

单目运算符

&

取地址运算符

&变量名

单目运算符

!

逻辑非运算符

!表达式

单目运算符

~

按位取反运算符

~表达式

单目运算符

sizeof

长度运算符

sizeof(表达式)

 

3

/

除

表达式/表达式

左到右

双目运算符

*

乘

表达式*表达式

双目运算符

%

余数(取模)

整型表达式/整型表达式

双目运算符

4

+

加

表达式+表达式

左到右

双目运算符

-

减

表达式-表达式

双目运算符

5

<<

左移

变量<<表达式

左到右

双目运算符

>>

右移

变量>>表达式

双目运算符

6

>

大于

表达式>表达式

左到右

双目运算符

>=

大于等于

表达式>=表达式

双目运算符

<

小于

表达式<表达式

双目运算符

<=

小于等于

表达式<=表达式

双目运算符

7

==

等于

表达式==表达式

左到右

双目运算符

!=

不等于

表达式!= 表达式

双目运算符

8

&

按位与

表达式&表达式

左到右

双目运算符

9

^

按位异或

表达式^表达式

左到右

双目运算符

10

|

按位或

表达式|表达式

左到右

双目运算符

11

&&

逻辑与

表达式&&表达式

左到右

双目运算符

12

||

逻辑或

表达式||表达式

左到右

双目运算符

13

?:

条件运算符

表达式1? 表达式2: 表达式3

右到左

三目运算符

14

=

赋值运算符

变量=表达式

右到左

 

/=

除后赋值

变量/=表达式

 

*=

乘后赋值

变量*=表达式

 

%=

取模后赋值

变量%=表达式

 

+=

加后赋值

变量+=表达式

 

-=

减后赋值

变量-=表达式

 

<<=

左移后赋值

变量<<=表达式

 

>>=

右移后赋值

变量>>=表达式

 

&=

按位与后赋值

变量&=表达式

 

^=

按位异或后赋值

变量^=表达式

 

|=

按位或后赋值

变量|=表达式

 

15

,

逗号运算符

表达式,表达式,…

左到右

从左向右顺序运算

 

C语言的自增自减运算 #include <stdio.h> int main() { int a = 10, b = 20, c = 30, d = 40; int a1 = ++a; int b1 = b++; int c1 = --c; int d1 = d--; printf("a=%d, a1=%d\n", a, a1); printf("b=%d, b1=%d\n", b, b1); printf("c=%d, c1=%d\n", c, c1); 阅读详情

相关推荐

别再手动拷贝文件了!用Keil MDK的Pack Installer一键搞定STM32上的RT-Thread Nano移植

本文详细介绍了如何使用Keil MDK的Pack Installer一键快速移植RT-Thread Nano到STM32项目,告别繁琐的手动拷贝和配置过程。通过自动化版本管理和依赖处理,移植时间从47分钟缩短至3分钟,大幅提升开发效率。文章还提供了实战步骤、高级配置技巧和常见问题解决方案,帮助开发者轻松实现RTOS集成。

weixin_29194817的博客 363

C语言基础知识:*p++与*(p++),*++p与*(++p),(*p)++ 与 ++(*p),++*p的详细理解

p++ 和 *(p++) 都返回 p 自增之前的值。*++p 和 *(++p) 都返回 p 自增之后指向的值。关键在于理解前缀自增(++p)和后缀自增(p++)之间的区别,以及它们与解引用操作(*)的结合方式。前缀自增先改变指针的值,然后返回新的指针值;后缀自增返回原指针值,然后改变指针的值。解引用操作(*)则用于获取指针当前指向的值。二、(*p)++ 与 ++(*p)在C和C++中,(*p)++ 和 ++(*p) 这两个表达式虽然看起来相似,尽管它们都涉及到指针p。

qq_65582400的博客 8472

【高等数值分析】Krylov子空间方法

文章目录1. 预备理论1.1 Krylov 子空间1.2 最佳逼近1.2.1 方法一:最佳平方逼近1.2.2 方法二:假设 AAA 对称正定1.2.3 方法三:残差2范数2. 基底正交化2.1 Arnoldi 过程(CGS)2.2 改进 Arnoldi 过程(MGS)2.3 Lanczos过程3. 方程组求解3.1 全正交方法 (FOM)3.2 D-Lanczos方法3.3 广义极小残量法(GMRES)3.4 MINRES 方法 1. 预备理论 现在需要求解一个大规模稀疏方程组 Ax=bAx=bAx=b,可

Glooow的博客 1万+

*p++是什么意思?

利用指针引用数组元素,比较方便灵活,有不少技巧。在专业人员中常喜欢用一些技巧,以使程序简洁。在看别人写的程序时可能会遇到一些令人混淆的情况,要仔细的分析。 请分析下面几种情况(设p开始时指向数组a的首元素(即p=a)。 ① 分析: p++; * pi; p++使p指向下一元素a[1]。然后若再执行* p,则得到下一个元素 a[1]的值 ② *p++; 由于++和*同优先级,结合方向为自右而左,因此它等价于 *(p++)值。 先引用p的值然后,实现*p的运算,然后使p自增1...

爱吃炸鸡的小猪's blog 2万+

从零开始:使用英伟达nx开发板部署目标检测算法的全过程

英伟达nx开发板烧录、依赖安装、开发板联网

weixin_51192760的博客 3760

AI+AB测试提升电商主图点击率实战指南

在电商运营中,主图点击率(CTR)是衡量商品吸引力的核心指标,直接影响转化率和订单增长。通过AI技术批量生成高质量主图素材,结合数据驱动的AB测试方法,可以显著提升点击率。AI工具如MidJourney和Stable Diffusion能够快速生成多样化视觉方案,而自动化处理流水线则确保素材规格统一。AB测试体系通过多维变量控制和流量分配策略,科学验证不同素材效果。这种方法特别适用于需要快速迭代的电商场景,某女装店铺案例显示CTR从1.2%提升至3.8%,验证了AI+数据协同优化的技术价值。

weixin_29058331的博客 298

*p++、*(p++)、*++p、*(++p)、(*p)++、++*p区别和用法

按从右向左的结合原则,++*p求值的顺序即为先进行“*”,然后再进行“++”运算,即先取出*p的值并赋给a,然后将*p的值arr[1]加1,但*p指向的内容不变。由于括号内优先运算,所以表达式先取出*p(假设为arr[1])的值并赋给a,然后讲*p的值arr[1]所代表的内容加1。再根据p++的运算先取值再自增,即为先取*p,然后进行p++的自增操作。再根据++p的运算先自增再取值,即为先进行p++的自增操作,然后取*p。此时*p指向的内容会发生改变,变为数组的下一位。--变量名/变量名--

W_XiangYu的博客 1万+

【20260309】【亲测可用】【异常】Get https://registry-1.docker.io/v2/: net/http: request canceled

【异常】Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection。

奶爸的编程之路,也就一周冷个三天 2万+

*p++、*(p++)、*++p、*(++p)的区别

首先我们看一下运算符的优先级,注意一下“*”和“++”的优先级。

主要记录嵌入式学习与开发过程。 2万+

分布式计算Ray框架面试题及参考答案

动态任务图执行引擎是一种能够根据任务之间的依赖关系和运行时的实际情况,动态构建和执行任务图的系统。在 Ray 中,动态任务图执行引擎允许任务在运行时根据数据可用性、计算资源状态等因素,灵活地决定后续任务的执行顺序和方式。对于 AI 应用来说,其往往具有动态性的特点。例如,在深度学习模型的训练过程中,可能需要根据训练的结果动态调整下一轮训练的参数、数据增强方式或者模型结构。动态任务图执行引擎可以很好地支持这些动态需求。它能够根据 AI 应用中各个任务的实时输出和依赖关系,动态地生成和调整任务图。

大模型大数据攻城狮的专栏 1349

HBV模型

据说mHM模型也是基于HBV模型原理。 网上不同版本的HBV模型稍有差别 def hbv_main(n_days, params, air_temp, prec, dpem): #n_days 模拟天数 #air_temp 每月温度 #prec 降水 #dpem 每月蒸发 Tsnow_thresh = 0.0 ca = 410. # Initialize arrays for the simiulation snow = np.zeros(air_temp.size

m0_46268055的博客 2326

*p++---详解*p++

C++运算符

weixin_45993336的博客 1258

一文就够-InfiniBand 技术全面解析:从原理到实践的通俗易懂指南

想象一下,在一个超级数据中心里,成千上万台服务器需要像蜜蜂群体一样高效协作。如果用传统的网络连接,就像让每只蜜蜂都排着队传递消息,效率极低。InfiniBand(简称 IB)就是为了解决这种 "通信拥堵" 而生的高速网络技术,它专门为高性能计算(HPC)、数据中心和云计算环境设计,就像给服务器之间搭建了多条高速公路,让数据可以飞驰而过。

jundao1997的专栏 1395

*p++

*p++是一个比较经典的运算符相关问题,主要注意以下两点: 1. 单目运算符结合律由右向左,先计算++再进行取值。 2. 如果要对值进行++运算的话那么就要先取值,后运算:(*p)++。 ...

Hello_MyDream的博客 2万+

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

c语言加加运算符是什么意思,c语言*p++是什么意思?

【*p++】的意思就是先取出指针p指向的地址单元的数据,之后再将该值加1,由于运算符【*】的优先级高于运算符【++】,所以是先取指针p指向的地址单元的数据,在p指向下一位置的数据。*p++的意思就是先取出指针p指向的地址单元的数据,之后再将该值加1,由于运算符 * 的优先级高于运算符 ++,所以是先取指针p指向的地址单元的数据,然后,p指向下一位置的数据。【推荐教程:C++教程】由于运算符 * 的...

weixin_35683697的博客 5433

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

c++ *p++ (*p)++ ++(*p)详细实战解读

0.前言 不管是我们平时看代码,还是自己写代码,经常都会看到诸如*p++,(*p)++, ++(*p)等写法。确实迷惑性比较强,而且一查资料,各种各样说法不一,容易让人云里雾里。因此,本文结合代码,给一个最准确详细的解释。 1.正确的结论 我们先上准确的结论: *p++: 返回的是指针p指向的值。如果p是数组,则为数组的第一个元素。然后再将指针p自增1。 (*p)++:返回的是指针p指向的值。如果p是数组,则为数组的第一个元素。然后再将该指针指向的值自增1。 ++(*p):获取指针p的位置取值,先自增1再返

bitcarmanlee的博客 8168

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

*p++、*(p++)、++*p、++(*p)、(*p)++

p存放的是a的地址,*p也等价于 a。但是在第四行,p指向的地址没有改变,但是*p的值发生了变化,这是由于(*p)等价于x[0](数组下标为0,位序是1),所以表达式 (*p)++ 相当于是使数组第一项数据元素自增。++*p=2 和 ++(*p) 等价,两个表达式的值都等于 *p 的值 +1(左++先自增后参与运算),指针p的值不变,p所指向的地址单元的值+1.*p++ 和 *(p++) 等价,两个表达式的值都等价于 *p的值,执行表达式之后,指针p的值增加一个地址单元长度,指向数组下一个位置;

dsy904123598的博客 1987

关于*p++ 的探究

自学者实验探究 *p++ 、*(p++)、*(p++)、++*p=2 和++(*p)的异同

qq_50789608的博客 1840

【指针】*p++、(*p)++、*++p、++(*p)都是什么东西?

指针真不戳,每日一晕

TinyHorse的博客 1万+

C语言中的*p++

C语言中的*p++ p = a; printf("*p = %d\n", *p); // 1 printf("p = %p\n", p); // 0x printf("\nOK\n\n"); printf("*p++ = %d\n", *

William_swl的博客 1238

C中的运算符优先级和结合性(*p++)

优先级和结合性 优先级是用来标识运算符在表达式中的运算顺序的,在求解表达式的值的时候,总是先按运算符的优先次序由高到低进行操作。但是,当一个运算对象两侧的运算符的优先级别相同时,则按运算符的结合性来确定表达式的运算顺序。 结合性是指同一优先级的运算符在表达式中操作的组织方向,即:当一个运算对象两侧的运算符的优先级别相同时,运算对象与运算符的结合顺序。 最容易搞混的莫过于运算符优先级处于第二级...

piracy 2283

C语言基础知识:*p++与*++p;(*p)++  与 ++(*p)的理解

首先查看C语言运算符优先级表,可以看到++和指针的*号运算优先级都是第二级。结合方向都是“右到左” *p++:等同于:*p;  p += 1; 解析:由于*和++的运算优先级一样,且是右结合。故*p++相当于*(p++),p先与++结合,然后p++整体再与*结合。前面陈述是一种最常见的错误,很多初学者也是这么理解的。但是,因为++后置的时候,本身含义就是先运算后增加1(运算指的是p...

baidu_37973494的博客 1万+

C语言指针(*p++、(*p)++、*(p++)、*++p、++*p的区别)

本次解决了自己学习过程中的知识点盲区,希望能够帮助到大家,互相学习。

D1557329860的博客 2270

指针 *p++ 与 (*p)++ 的区别

指针 C语言的指针(pointer),是内存中存储单元的存储地址,指针变量就是专门用来存储其他变量的地址的变量。 用指针要小心,搞不好会死机。 &是地址运算符,用来表示变量的地址,*是类型说明符,用来说明其后的变量是个指针,如果*在表达式中出现,那么就表示该指针变量所指向的变量。 上代码 int a,*p; p=&a; 那么*p就是a了。 那么*p++与(*p)++和a++有什么关系? 根据括号运算符的最高优先级,我们可以肯定,(*p)++和a++应该是等价的。 那*p+

笔记 7590

*p++和*++p的区别

接下来,通过示例彻底理解自增运算符的两种用法(自减的用法与之类似,只不过是加1变成了减1)。     1、++i和i++的区别     如清单1(注意代码中的注释):  #include int main(void) { int a, b, i = 7; i++; //等价于i = i + 1; ++i; //等价于i = i + 1;

tanglinux 16万+

关于*p++与*++p

假设 p 是指向数组 arr 中第 n 个元素的指针,那么 *p++、*++p、(*p)++ 分别是什么意思呢? *p++ 等价于 *(p++),表示先取得第 n 个元素的值,再将 p 指向下一个元素。 *++p 等价于 *(++p),会先进行 ++p 运算,使得 p 的值增加,指向下一个元素,整体上相当于 *(p+1),所以会获得第 n+1 个数组元素的值。 如果加了括号就先算括号里的,如,(*p)++会先取得第 n 个元素的值,再对该元素的值加 1。 ...

weixin_55811411的博客 4952
上一篇: Ogre各种场景管理器以及和插件关系深入分析
下一篇: OGRE地形初步(附三角形简化方法概述)
HNFXS985
博客等级 码龄14年 219粉丝 150原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值