如何一句句编译 c语言,【C语言复习(五)】由++,--操作符的使用简单认识C编译器的“贪心法”编译机制...

C语言中自增和自减操作符的使用有时真的令人头疼,如果不知道编译器如何处理它们,就无法正确预计计算的结果。

例如下面的例子:

int i=3;

int j=(++i)+(++i)+(++i);

第一次看到这段代码时,我觉得结果会是15,因为我想括号内的部分应该会被从左到右优先计算,那么结果就是4+5+6=15;

可是在Gcc中编译运行的结果却是16;在Visual Studio中编译运行的结果为:18;为什么会这样呢?

先说VS中的做法,它在编译时会觉得我们所加的三个括号内的内容优先级最高,那么它先计算括号内的,也就是将i自增了3次,变成了6,然后再想加,结果为18;

而在gcc中,应该是先计算了(++i)+(++i),即是先计算括号内的两次自增,然后再相加:5+5=10;最后计算:10+(++i),结果为16;

再看如下的示例:

int i = 3;

int j = 0;

j=++i+++i+++i;

这好像是一道面试题,初次看见,真不知道结果如何,编译后才发现编译器会报错。后来结合C编译器的“贪心法”才大概明白为何如此;以下是我个人的分析理解,是否正确没有考证;

C编译器贪心法的原则大概是:

编译器处理的每个“表达式”应该尽可能的多包含字符;

编译器从左到右一个一个尽可能多的读取字符;

当即将读入的字符不能和已读入的字符组成合法“表达式”为止。

据此分析上述示例:编译器读取到’+’,由于无法构成表达式,因此向后读取:’+’,还是无法构成,再读取:’i’,构成表达式了,由于贪心,想一次性多读取字符,故再读取:’+’,此时读取的表达式为:++i+,无法构成表达式,但是再读取一个有可能构成一个加法的表达式,因此再读取一个:’+’,此时读取的表达式为:++i++,这时候编译器就看不懂了,无论后面读取什么都无法构成有效的表达式,因此编译器就尝试着先来处理:++i++,于是它先计算:++i的值为4,然后表达式变成了:4++,这里问题就出来了,4是一个常量,如何自增呢??因此它会提示:表达式的左值必须是可修改的!(|error: lvalue required as increment operand)

同理,可以看如下的例子:

a+++b;

如上语句是等价于:a++ + b??还是a + ++b 呢??

同理,用贪心法分析:编译器读取到’a’后,继续读取:’+’,它会认为这是可行的,于是接着读取:’+’,这时的结果为:a++,自增表达式啊,合理的,于是接着读取:’+’,此时读入的为:a+++,因此编译器知道要先处理a++了,于是计算a++,此时a++计算后为一个值,表达式还能再读入一个字符,于是再读取一次:’b’,是合理的,就尝试着再读取,发现已经到了句末’;’,表示此语句已经结束,因此原句等价于:”a++ + b;”

一道面试题:

假如有如下语句,请判断它们合法吗?如果合法,请写入表达式的值:

int a = 4;

a+=(a++);

a+=(++a);

(a++) += (++a);

答案:

1.合法,值为9

2.合法,值为10

3.不合法

分析:

a+=(a++);表达式中先处理括号内的表达式,因为为后置++,所以“先使用a的值,再让a自增1”,等价于:4,a=a+1;因此括号内计算完成后a=5;

然后再计算a+=4;所以值为9;

(a++) += (++a);按照上面1的方法,先计算括号内的,所以应该是(a++),“先使用a的值,再让a自增1”,等价于:4,a=a+1=5; 然后再计算(++a),等价于:a=a+1=6,6; 最后计算:4+=6; 这个表达式显然不成立,4是一个常量值!所以编译器会报错:表达式必须是可修改的左值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值