a+++++b之我见

今天在看c陷阱与缺陷这本书时,无意中发现了这条语句,a+++++b,我最初的理解是a++  +  +++b,但是在VS2010和IAR WorkBench上跑都是编译错误,于是我便查了资料:

int a=1,b=1; int c=a+++++b; printf("c=%d/n",c); 这段代码是无法通过编译的。 解释如下:
1、首先介绍一些基本的概念 1)、大嘴法,又称贪心法:
如果(编译器的)输入流截止至某个字符之前都已经被分解为一个个符号,那么下一个符号将包括从该字符起之后可能组成一个
符号的最长字符串。也就是说,每一个符号应该包含尽可能多的字符。换句话说,编译器将程序分解成符号的方法是,从左到右一个字符一个字符地读入
,如果该字符可能组成一个符号,那么再读入下一个字符,判断已经读入的两个字符组成的字符串是否可能是一个符号的组成部分,如果能继续读入下一个字符,重复判断,直到读入的字符组成的字符串已不再可能组成一个有意义的符号。
举个例子,如a---b 与表达式a-- -b的含义相同,而与a- --b的含义不同。 再比如:b=a/*p /* p指向除数 */;
该语句的本意是用a除以p所指向的值,把所得的商再赋给b。而实际上,/*被编译器理解为一段注释的开始,编译器将不断地读入字符,
直到*/出现为止。因此要重写:b=a / *p /* p指向除数 */; 更清楚点就是b=a/(*p) /* p指向除数 */;此所谓二义性。 2)、左值和右值
左值就是在赋值中可以放在赋值操作符两边的值,比如: int a = 1; double b = 2.0 a = b; b = a;
这里a和b都是左值,一切变量都是左值,但const量是例外。 右值则是只可以放在赋值操作符右边的值,比如: int a = 0; char *b =
"hello"; 3 = a; // ERROR "howdy" = b // ERROR
这里3和"howdy"都是右值,所以不能放在赋值操作符左边,一切常数、字符和字符串都是右值。 i 和 -i 都是表达式,但一个是左值(i),一个是右值(-i)。
++,--这两种操作符要求作用于左值,所以i++合法,(-i)++不合法。 2、a+++++b的含义: 唯一有意义的解析方式是:a ++ + ++ b
可是,根据“大嘴法”规则,应该被分解为:a ++ ++ +b ,这个式子从语法上来讲是不正确的,它等价于:((a++)++) +b
但是,a++的结果是不能作为左值的,因此编译器不会接受a++作为后面的++运算符的操作数。这样,如果遵循了解析词法二义性问题的规则,上例的解析从语法上来说又没有意义。因此,在编程实践中,谨慎的做法就是尽量避免使用类似的结构,除非你非常清楚这些结构的含义。
参考: 1、《C陷阱和缺陷》

posted @ 2013-03-30 15:53  醉剑客  阅读(212)  评论(0编辑  收藏  举报