自增自减运算符的优先级为2(仅低于中小括号,成员对象选择符,成员指针选择符),右结合性。
2.7.1 前置与后置的区别#includeint main() { //后置 int i = 0, j; j = (i++) + (i++) + (i++); printf("j=%dni=%dn",j,i); //前置 i = 0; j = (++i) + (++i) + (++i); printf("j=%dni=%dn", j, i); }
对于以上代码,执行结果应该是怎样的呢?
对于后置情况来说:由于后置中的先用后变中的“变”只有在遇到逗号、分号等表示该执行单位结束的运算符时才会自增自减。所以此处的表达式实际上等同于j=i+i+i;i=i+1;i=i+1;i=i+1;
对于前置情况来说:C语言的标准没有准确说明,因此其值因编译器而定。对于VS来说,其等同于i=i+1;i=i+1;i=i+1;j=i+i+i;也就说先执行自增自减再执行其他运算。
那么,把上面的括号去掉会怎么样呢?
#includeint main() { //后置 int i = 0, j; j = i++ + i++ + i++; printf("j=%dni=%dn",j,i); //前置 i = 0; j = ++i++ + i++ + i; printf("j=%dni=%dn", j, i); int i=0, j=0; i++ + j; i++++ + j; }
C语言有一个贪心策略,就是说当有多个符号在一起的时候,会从左往右尽可能将更多的符号组成一个运算符。
因此对于后置来说,其表达式等同于j = (i++) + (i++) + (i++); 对于前置来说,其表达式等同于j =((++i)++)+(i++)+i;因此该表达式格式也是错误的,因为自增自减不能作为左值,也就是不能被赋值。
2.7.2 自增自减与逗号表达式#includeint main() { //后置 int i = 0, j; j = (i++,i++,i++); printf("j=%dni=%dn", j, i); //前置 i = 0; j = (++i,++i,++i); printf("j=%dni=%dn", j, i); }
对于后置来说:由于后置是先用后变,而自增自减运算符的优先级又低于逗号运算符,所以执行顺序为i=i+1;i=i+1;j=;i=i+1;
对于前置来说:由于前置是先变后用,且自增自减运算在遇到以逗号或分号的单位执行结束运算符时就会"变",因此执行顺序为i=i+1,i=i+1,i=i+1,j=i;
2.7.3 自增自减与逻辑运算符#includeint main() { //前置 int i = 0,j; j = ++i || --i && i--; printf("j=%dni=%dn", j, i); //后置 i = 0; j = i++ || --i && i--; printf("j=%dni=%dn", j, i); }
由于自增自减运算符优先级高于逻辑运算符,且逻辑运算符有短路特性(对于逻辑或,只要其左侧表达式为真则结果为真,其右侧表达式不再执行;对于逻辑与,只要其左侧表达式为假则结果为假,其右侧表达式不在执行),因此执行顺序为i=i+1;j=i;逻辑或右侧的表达式不在执行。
2.7.4 自增自减与函数实参#includevoid fun(int i, int j, int k) { printf("i=%dn", i); printf("j=%dn", j); printf("k=%dn", k); printf("n"); } void fun1(int i, int j, int k,int z) { printf("i=%dn", i); printf("j=%dn", j); printf("k=%dn", k); printf("z=%dn", z); } int main() { int x = 0; fun(x, ++x, --x); fun1(--x, ++x, x, ++x); x = 0; fun(x, x++, x--); }
由于函数执行时其实参值是按照从右向左的顺序入栈的,因此对于函数实参中的自增自减运算要特别注意!
对于前置来说:只有执行单位结束其值才会变,再结合函数实参的入栈方式,所以fun(x, ++x, --x);的执行顺序是:k=x;j=x;i=x;x=x-1;x=x+1;x=x;同理可知fun1(–x, ++x, x, ++x);的执行顺序。
对于后置来说:其就直接先用后变就可以,因此fun(x, x++, x–);执行顺序为:k=x;x=x-1;j=x;x=x+1;i=x;x=x;
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)