C语言,{*s++ += 7} != {*s++ = *s++ + 7}

博客题目也许有些奇怪:{*s++ += 7} != {*s++ = *s++ + 7}

先看一下代码,一个小问题:

#include<stdio.h>
int *f(int *s)
{
	s += 1;printf("%p\n",s);
	s[1] += 6;
	*s++ +=7; 
	printf("%p\n",s);
	return s;
}
main()
{
	int a[5]={1,2,3,4,5},*p;
	printf("%p,%p,%p,%p,%p\n",&a[0],&a[1],&a[2],&a[3],&a[4]);
	p=f(&a[1]);
	printf("%d,%d,%d,%d\n",a[1],a[2],*p,p[1]);
}

运算结果:


现在这个代码的运行结果似乎有疑问,与预算的不相同

我们主要的关注对象是*s++ += 7部分,代码作用不解释了。

我们先看着个问题:

int sum=0;
sum += 3;

首先想到的是:sum += 3; 等价于sum = sum + 3;

这显然没有问题,优先处理的是+=运算符,将其拆开还原即可。

回到问题*s++ += 7上,运算符出现了:++(右自增),*(取值),+=三种。

通常根据C语言的运算符知识会作出如下思考:优先级中++ 优于 * 优于 += ,所以在处理*s++ += 7时首要考虑的是++运算符而不是+=。

*s++ += 7;等价于*(s++) += 7;

(s++)先取值在加一,可能在本题中会有人想到*s++ += 7;中的可以思考如下:

*(s++) += 7;中先使用s的值(s的值是一个地址),之后进行*s的取值,然后++发挥作用使得*s的值加一,最后再到+=的运算符,将式子还原。可以发现其中的问题是:++发挥作用使得*s的值加一,加一后的式子变成了:常数 += 常数 ;

显然这种式子是不被C语言所允许的,但是本文开始出就已经给出了程序的运算结果,说明代码没问题!

现在思考出错的原因,显然思路在加一的操作后出了错误,现在给出合理的解释(这里只是猜想):

*(s++) += 7;

①先处理(s++),对s的态度是先使用s的值;

②*(s)取值;

③*(s)取值后不进行 ++ 原本的加一行为,而是执行+=操作符:

④原式变为:( s指针往右加一 )= *s + 7 ;

⑤结果是:原地址对应的值执行+7,+7后将结果10赋给地址,地址只是往后移动一次。

解释右侧写为(s指针往右加一 )的原因:s++先是使用s的地址,在等待s的地址加一,由于上面②③操作使得加一操作未能得到执行,因此将其后续操作放在等式的左边。

以上的猜测过程完整的解释了开始的代码运行结果。

猜想的作用与验证思路:①是解释问题的原因②解释原因后使用猜想的方法进行预测③实验验证

现在进行预测:

将开始代码修改,将*s++ +=7; 改为*s++ *=7; 其余部分不变

代码:

#include<stdio.h>
int *f(int *s)
{
	s += 1;printf("%p\n",s);
	s[1] += 6;
	*s++ *=7; //还可以改为 -=;/=;%=
	printf("%p\n",s);
	return s;
}
main()
{
	int a[5]={1,2,3,4,5},*p;
	printf("%p,%p,%p,%p,%p\n",&a[0],&a[1],&a[2],&a[3],&a[4]);
	p=f(&a[1]);
	printf("%d,%d,%d,%d\n",a[1],a[2],*p,p[1]);
}

预测结果:2,21,10,5

实际运行结果是:

预测与实际运行结果相同,猜想正确。因此以后遇见*s++ += 7类似问题时就可以按猜想的过程解决。

PS:由于本人能力有限,文中出现错误的地方希望能得到大家的指正,谢谢!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值