C语言自增符号与括号,C语言杂谈(二)自增运算符++与间接访问运算符*的结合关系和应用模式...

自增运算符++有前缀和后缀两种,在搭配间接访问运算符*时,因为顺序、括号和结合关系的影响,很容易让人产生误解,产生错误的结果,这篇文章来详细分析一下这几种运算符的不同搭配情况。

++、--和*的优先级顺序

在C语言运算符的优先级顺序中,后缀的++和--运算符运算优先级16,结合关系是从左到右;简介访问运算符*、前缀++和--运算符运算优先级15,结合关系是从右到左。根据这个关系,可以分析出不同情况下的应用。为了更直观的体现,有以下的例子。

举例说明

有数组a[5],值分别为10,11,12,13,14;有指针p指向a[0];另有指针q和整数b。这里注意的是,每段代码开始前,a数组的值和p指针都会回复初始状态。(在一开始写这些测试代码时,忽视了回复初值的问题,导致很多奇怪的错误,比如p已经不再指向a[0],或者a[0]本身已经改变了。)

1.后缀++

p =a;

q= p++;

p指向a[1]值为11,q指向a[0]值为10。说明后缀自增运算符,返回的是自增前的值。

2.前缀++

p =a;

q= ++p;

p指向a[1]值为11,q指向a[1]值为11。说明前缀自增运算符,返回的是自增后的值。

3.*p++

p =a;

b= *p++;

p指向11,b值为10。此时先执行p++,p自增,指向a[1]。p++的值为自增前的值,即a[0]的地址,a[0]的值赋给b。

4.*(p++)

p =a;

b= *(p++);

结果与3相同。*与++运算符优先级相同,运算顺序是自右向左。

5.(*p)++

p =a;

b= (*p)++;

此时虽然结果与3相同,但这时是先取p指向的值即a[0],a[0]自增即a[0]的值变成11,自增是后缀的,返回自增前的值,即10。结果相同,但原理还有很大的差别。

6. *++p

p =a;

b= *++p;

p指向11,b值为11。先执行++p,p自增,指向a[1],++p的值为自增后的值,即a[1]的地址,a[1]的值赋给b。

7.*(++p)

p =a;

b= *(++p);

与6结果相同,*与++运算符优先级相同,运算顺序是自右向左。

8.++(*p)

p =a;

b= ++(*p);

p指向11,b值为11,先取p指向a[0]值为10,a[0]的值自增变成11,前缀自增返回值为11赋给b。

9. ++*p

p =a;

b= ++*p;

结果同8,*与++运算符优先级相同,运算顺序是自右向左。

总结

第一个原则就是前缀值为变化后,后缀值为变化前。第二个原则,*++优先级相同,读的时候从右向左。这些都是本人自己试着总结的,如有错误请多指正,希望对有疑惑的朋友有所帮助。

完整代码

/*本程序用来测试前缀自增运算符,后缀自增运算符,取内容符号的运算优先级以及顺序带来的返回值的影响*/#include"stdio.h"

void myPrint(int n,int j, intk)

{

printf("no.%d:p->%d, q->%d\n", n,j, k);

}void myPrintNew(int n,int j, intk)

{

printf("no.%d:p->%d, b->%d\n", n,j, k);

}void init(int a[5])

{

a[0] = 10;

a[1] = 11;

a[2] = 12;

a[3] = 13;

a[4] = 14;

}//防止某些测试的操作改变了数组的值,在每次使用数组之前使用初始化函数

int main(int argc, char*argv)

{//int a[5] = { 10, 11, 12, 13, 14 }, *p,*q,b;

int a[5] ,*p, *q, b;

init(a);//1.

init(a);

p=a;

q= p++;

myPrint(1,*p, *q);//p指向11,q指向10//后缀自增运算符,返回的是自增前的值//2.

init(a);

p=a;

q= ++p;

myPrint(2,*p, *q);//p指向11,q指向11//前缀自增运算符,返回的是自增后的值//1,2:阅读顺序:从左到右//3.

init(a);

p=a;

b= *p++;

myPrintNew(3,*p, b);//p指向11,b值为10//先执行p++,p自增,指向a[1],p++的值为自增前的值(见1),即a[0]的地址,a[0]的值赋给b//4.

init(a);

p=a;

b= *(p++);

myPrintNew(4,*p, b);//结果与3相同//*与++运算符优先级相同,运算顺序是自右向左//5.

init(a);

p=a;

b= (*p)++;

myPrintNew(5,*p, b);//结果与3相同,但这时是先取p指向的值即a[0],a[0]自增即a[0]的值变成11,自增是后缀的,返回自增前的值,即10//与8对照//6。

init(a);

p=a;

b= *++p;

myPrintNew(6, *p, b);//p指向11,b值为11//先执行++p,p自增,指向a[1],++p的值为自增后的值(见2),即a[1]的地址,a[1]的值赋给b//7.

init(a);

p=a;

b= *(++p);

myPrintNew(7, *p, b);//与6结果相同//*与++运算符优先级相同,运算顺序是自右向左//8

init(a);

p=a;

b= ++(*p);

myPrintNew(8, *p, b);//p指向11,b值为11//先取p指向a[0]值为10,a[0]的值自增变成11,前缀自增返回值为11赋给b//9??

init(a);

p=a;

b= ++*p;

myPrintNew(9, *p, b);//结果同8//*与++运算符优先级相同,运算顺序是自右向左

return 0;

}

运行结果

98e683555f28e0b2bff6ea623a016531.png

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值