在线配资哪个平台好 【未来虫教育】C语言中自增自减的编译原理
发布日期:2025-01-13 02:43 点击次数:121
自增自减规则
i++ 与 ++i 的主要区别有两个:
1、 i++ 返回原来的值,++i 返回加1后的值。
2、 i++ 不能作为左值,而++i 可以。
毫无疑问大家都知道第一点(不清楚的看下下面的实现代码就了然了),我们重点说下第二点。
首先解释下什么是左值(以下两段引用自中文维基百科『右值引用』词条)。
左值是对应内存中有确定存储地址的对象的表达式的值,而右值是所有不是左值的表达式的值。
一般来说,左值是可以放到赋值符号左边的变量。但
能否被赋值不是区分左值与右值的依据。比如,C++的const左值是不可赋值的;而作为临时对象的右值可能允许被赋值。左值与右值的根本区别在于是否允许取地址&运算符获得对应的内存地址。
比如,
展开剩余79%
int i = 0;
int *p1 = &(++i); //正确
int *p2 = &(i++); //错误
++i = 1; //正确
i++ = 5; //错误
那么为什么『i++ 不能作为左值,而++i 可以』?
看它们各自的实现就一目了然了:
// 前缀形式:
int& int::operator++() //这里返回的是一个引用形式,就是说函数返回值也可以作为一个左值使用
{//函数本身无参,意味着是在自身空间内增加1的
*this += 1; // 增加
return *this; // 取回值
从融资结构来看,信用债是房地产企业的主要融资模式,10月融资规模共217亿元,同比增长44.9%,环比增长27.7%,占比近75%。同期,ABS融资约73亿元,同环比均有所下降;海外债则无新增发行。
}
//后缀形式:
const int int::operator++(int) //函数返回值是一个非左值型的,与前缀形式的差别所在。
{//函数带参,说明有另外的空间开辟
int oldValue = *this; // 取回值
++(*this); // 增加
return oldValue; // 返回被取回的值
}
如上所示,i++ 最后返回的是一个临时变量,而临时变量是右值。
运算符读取规则
C语言对于解决这个问题的解决方案可以归纳为一个很简单的规则:每一个符号应该包含尽可能多的字符。也就是说,编译器将程序分解成符号的方法是:从左到右一个一个字符的读入,字符一个字符地读入,如果该字符可能组成一个符号,那么再读入下一个字符,判断已经读入的两个字符组成的字符串是否可能是一个符号的组成部分;如果可能,继续读入下一个字符,重复上述判断,直到读入的字符组成的字符串已不再可能组成一个有意义的符号。这个处理策略有时被称为“贪心法”,或者,更口语化一点,称为“大嘴法”,Kernighan与Ritchie对这个方法的表述如下,“如果(编译器的)输入流截止至某个字符之前都已经被分解为一个个符号,那么下一个号将包括从该字符之后可能组成一个符号的最长字符串。”
---《C陷阱和缺陷》 第八页
编译器编译情况
自增(后缀):
Turbo C中,先统一取值后依次自增;
VS中,从左向右依次取值自增;
int a,i=5;
a=i+++i+++i++;
//按照贪心算法,结果为(i++)+(i++)+(i++)
//Turbo C中:a=5+5+55=15,i=8
//VS中:a=5+6+7=18,i=8
以下编译出错
int a,i=5;
a=++i+++i+++i;
//编译错误
//编译器编译后,((++i)++)+(i++)+i
++i返回的是一个引用形式,无法在对(++i)在进行自增。
发布于:湖南省