初学C语言:小小的运算符,大大的隐患

前言:本人为C语言初学者,学识尚浅,研究程度存在很大的局限性,眼界很窄。以下所有观点仅代表个人见解和思路,各位游刃有余的前辈可以给予批评和指正!各位与鄙人同路的学子可相互探讨、发表看法,交换观点!

在之前的一篇文章中,剖析了每个运算符的基本用法,当然,只是简单的分析和了解它们,如有需要,转至:初学C语言:运算符,一个也不放过

但这些运算符,就真如所见那般如此简单的运用吗?

我们看一下如下代码:

result = a * b + c * d + e * f;

这个表达式该如何计算?

我想大多数初学者的想法都是:

这符合我们的定性思维,但是计算机不是人,它的要求是遵循相邻操作符优先级高的先运算。 

以上运算符中,14相邻,42相邻,25相邻,53相邻。

按道理,我们只需要保证 + 比 * 后运算就OK,所以我们能不能把顺序改成这样呢?

我们发现,相邻运算符的优先级是符合运算规则的, 13相邻,32相邻,25相邻,54相邻。

所以我们发现,我们并不能保证第一个 + 在最后一个 * 的后面运算。

或许你想说:不管以怎样的顺序,结果不都是一样的吗?如果a~f这些字母不是变量而是表达式或者是被调函数呢?如果这些表达式或者被调函数会影响后面表达式或者被调函数的返回结果,那么不同的运算顺序不就会导致截然不同的结果了吗?

所以如果我们心中有运算顺序,最好最好,请把他们分条写出来,比如我的运算顺序就如上图,13254,那么我就应该这样写:

int result = 0;
result = a * b;
result = result + c * d;
result = result + e * f;

不要偷这多写几行代码的懒~不然每一个编译器都能教你做人!

比如非常经典的例子:

int a = 1;

int result = (++a) + (++a) + (++a);

请问,result的结果是?我靠,这不是纯纯的垃圾代码吗?

自增运算符的优先级比+高(括号和自增运算符是等价的,也就是说如果括号要先运算就是自增运算符要先运算,所以我这里没有提及括号,但是概念是一样的),所以我们要保证相邻的自增运算符和加号是自增运算符先运算,其实运算顺序仍然是以上举例的两种,如果不方便看,我再画一遍:

 

如果按第一种计算:
1.++a,a变成2

2.++a,a变成3

3.++a,a变成4

4、5:4 + 4 + 4 = 12;

如果按照第二种计算:

1.++a,a变成2

2.++a,a变成3

3.3 + 3 = 6;

4.++a,变成4

5.6 + 4 = 10;

就是这么离谱,这也就是VS(12)和Linux(10)编译的两种结果的由来,如果感兴趣,我们转到反汇编,可以看到它究竟是怎么做的: 

这里的代码我不做详解,仅供有兴趣的小伙伴钻研(其实就是我说的第一种,结果为12)

这里提及一些汇编指令:mov是移动,比如把a的数据移动到eax中,eax是寄存器,同理ecx也是;inc是+1。其实仔细分析也就是上述第一种情况的计算原理。

如果上面的概念理解了,那么我们再来看看如下代码:

result = c + --c;

 这里该怎么算?

或许你有是脱口而出,这不就是c自减之后再加c?

nonono,-- 的优先级肯定比 + 高,所以自减在相加之前,mou问题,但是第一个c什么时候准备好?如果第一个c先准备好,然后c自减,(假设c是5)那么就变成了 5 + 4 = 9;但是如果是c先自减然后再准备好第一个c,那么就变成了4 + 4 = 8;所以,如果你心里有顺序,一定要拆开写...

希望这些内容能对你有些帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thepale2022

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值