关于b=a++的计算和赋值

优先级只是规定两个“相邻”的运算符所引领的“表达式运算”在“逻辑上”的先后顺序
首先,比如a+b+c*d,乘法比加法优先级高,但是,这里我们完全可以先算a+b,后算c*d,因为第一个+和后面的*不相邻,不相干,这是一个条件
其次,规定的顺序仅是“表达式求值”,这个下面再详细说
再次,是逻辑上的顺序,实际上有可能缺失一些运算,比如a&&b+c,虽然+比&&高,这里逻辑上也的确是得先算+再&&,但是由于&&有短路特性,所以确切说是只有“有必要计算b+c”时候,我们才计算加法,然后&&,这是从表达式角度来看,实际上&&并不是一个计算操作,而是一段类似if else的逻辑代码

然后详细说下“表达式求值”相关的问题:
c=d++
这个表达式是有两个运算,从优先级来说++是要先算,然后=后算,实际也是这么执行的:
第一步:对d++表达式求值,即做++运算,结果假设存在tmp临时变量,根据定义值则为d自增前的值
第二步:对c=tmp做表达式求值,根据赋值表达式的定义,其结果为tmp的值,如果这个表达式是一个子表达式(比如你写的是printf("%d", c=d++);),则这个值就被上层表达式求值继续用到

诶?你是不是觉得漏了两个地方,一个是d的自增,一个是c的赋值?
嗯这就是关键了,自增和赋值的操作是“副作用”,而不是表达式求值的一部分,其实你完全可以看做是和表达式求值分离的,之所以为“副”作用,说的就是“表达式求值”才是主业,改变内存的副作用只是“兼职”,C语言对副作用起作用时机的定义是,在下一个顺序点到来之前的任何时候,比如
a+(c=d++);
按照C的规定,这里,顺序点是在“全表达式”结束后,而c和d的值的改变可以在此之前任何时候起作用,展开伪码:
tmp = d //表达式求值:++运算
tmp = tmp //表达式求值:=运算
a + tmp //表达式求值,+运算
可以看到,是严格按照优先级来的,++先算,=后算(因为在括号里),+最后算
d=d+1和c=tmp在什么时候执行呢,可以分别插在上面三步的任意位置,这个跟优先级一点关系都没有

顺便说下,副作用的时机在新的C++标准,好像是14还是17,做了改动,更规范化了
最后说下,如果你多个副作用是改了一块内存,或对这块内存同时有读写,由于副作用时机的不确定性,执行结果也是不确定的,这也是为什么严禁写出i+++i++或a[i]=i++之类代码的原因

 

不不不,这是你理解的问题,这个操作符优先级最高,但它是做了这么一件事:让变量自增,同时返回自增之前的值
对应的返回自增之后的值的运算符是++d
看一下

while(*c){
    *(new_str++) = *(c++);
}

就知道为什么有用了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值