C语言中的++、–即自增、自减是很令人头疼的。
刚好看到一个问题,一起分析一下。
int i = 3;
(++i) + (++i) + (++i);
你觉得这个表达式的值是多少?
如果你觉得是15,那完了,你c语言学的跟我一样,太烂了。
我去查了一下,有说是16,还有说是18的。分析了一下,好像都有道理。
如果是都先做完括号内的,那答案就是18了。
但编译器如果认为前两个括号做完,然后会认为后面是加号,和前面一样的,前面两个便可以先进行计算,结果就是16。
分析完了,就直接去运行看结果吧,我使用了gcc和g++编译,结果都是16。后来问大佬,查资料,据说这是c语言的灰色地带,没有明确规定,结果会因编译器规则不同而不同。
继续看另一段代码:
#include <stdio.h>
int main()
{
int i = 0;
int j = ++i+++i+++i;//报错1
int a = 1;
int b = 2;
int c = a+++b;
int* p = &a;
b = b/*p;//报错2
return 0;
}
你觉得j的结果是多少?
实际是这里会报错,
[Error] lvalue required as increment operand
说左值不可以增运算,为什么报这错呢?因为编译器是贪心法阅读代码:
编译器处理的每个符号应该尽可能多的包含字符
编译器以从左向右的顺序一个一个尽可能多的读入字符
当即将读入的字符不可能和已读入的字符组成合法符号为止
所以看上面的j那一行可分析到一次读,会一直读到++i++为止,我们知道++i返回是值,值自然不可以进行运算,所以报错。我们通常应该加上括号,已明确运算顺序。
修改之后,再编译,发现上面的第二个报错,这个又为什么报错呢,如果用ide编辑代码,就会发现从/*开始都认为是注释了。就是我们之前提到的编译器的贪心法了,认为是注释开头了。
对此,通常编程规范中都会有规定,对于运算都明确加括号以明确运算顺序。另外就是我们会发现,使用很多ide编程的时候,在我们例如加上结束符之后,会帮我们格式化,这时你都会发现运算对象和运算符之间都会有空格,其实这不光光是美观,编译器会识别空格,知道这里是读入结束。
了解了这些知识,修改上面的代码:
#include <stdio.h>
int main()
{
int i = 0;
int j = ++i+ ++i+ ++i;
int a = 1;
int b = 2;
int c = a+++b;
int* p = &a;
b = b/ *p;
return 0;
}
不光看的清晰,编译运行完美了。