(进阶)C函数调用

staic 变量使用的相关问题

笔者最近看《C与指针》这本书,发现了许多从前学习时没有遇见的有趣问题。

最让笔者震惊的是第五章5.8习题中第二题,让笔者又从头认真学习了一遍C语言的 static 变量。
在这里插入图片描述

在这里插入图片描述

代码

int fun(){
	static int count = 1;
	return ++count;
}

int main(){
	int answer ;
	answer = fun() - fun() * fun() ;
	printf("%d\n",answer);
	return 0;
}

刚开始,笔者用一向的惯性思维思考这个问题。

  • 首先,从主函数进入,answer 的值未知,执行到主函数第二条语句,answer 被赋值为 fun() + fun() * fun() ,毫无疑问,第一个肯定执行优先级高的乘法。 因此,进入左数第二个 fun() 函数内部。
  • 其次,进入fun() 内部,因为 count 是静态变量,++count 的意义是先加再return,因此执行完return 语句之后 count 的值应该是2;
  • 接着,左数第二个fun() 的值是2,接下来进入左数第三个 fun() 函数内部。 因此 count 被重现赋值为“1”,因此返回值应该与左数第二个 fun() 返回值相同为2;
  • 左数第一个同理,返回值为2.

因此笔者自信地写下了answer 的值为 -2.
结果打开vim 编辑之后,发现事情没有这么简单。。。
在这里插入图片描述

是的,输出的结果是 -10。 嗯??????
在这里插入图片描述
身为一位新时代的年轻人,不禁想问一句,“什么鬼操作???”

不如吃茶去。。。
脑子一机灵,不如化简?
不错不错,根据笔者的想法,将源代码的主函数化为:

int answer;
	int a = fun();
	//printf("a %d\n", a);
	int b = fun();
	//printf("b %d\n", b);
	//printf("mul %d\n", a*b);
	answer= fun() - a * b;
	printf("%d\n", answer);

vim 执行完之后结果,恰好是笔者写的 -2 。当然,这个结果是完全错误的。。。
到底问题出在哪了呢?

  • 问题在这,static 有点特殊,第一次进入fun 函数时,count 被赋值为1, 接着 return 语句中,count 自加1,这时, count 的值为2。
  • 接着执行进入第二个 fun 时,这时 static int count = 1 并没有起到赋值的作用,编译器直接忽略这一语句。执行了 return 语句,这时 count 的值为3。
  • 同理,第三个 fun 执行完之后,count 的值可得到为4。

那么?答案不是 4-2*3 = -2 么?不是,事情没有那么简单。。。

在这里插入图片描述

继续继续,我们认真观察这一天语句:

answer = fun() - fun() * fun() ;

必须要清楚的是,fun() 不是一个变量,而是一个返回值。fun() 函数地址是一定的,因此其实结果是 answer = 4 - 4*4 ,这样结果就是 -10了么。 是这样么???

想知道我们的推理是否正确,不如将 “-” 改为 “+”。

因此我们将源代码这条语句改为:

answer = fun() + fun() * fun() ;

如果按照我们的推理,得到的结果应该是20 才对。
在这里插入图片描述

14??? 不按常量出牌啊老铁。
证明我们的想法是完全错误的。。。

不过,我们已经将函数的返回值与变量值之间的关系区分开了。这时看到《C与指针》上的一段话:

在这里插入图片描述
在这里插入图片描述

什么意思呢?
不如让我们抛弃算数逻辑的先后顺序。 从左向右执行下去。

  • 首先,执行左边第一个 fun() 函数,这时 count 返回2,第一个 fun() 返回了2.
  • 接着执行第二个 fun() ,这时 count 为3, fun()
    的返回值为3.
  • 最后执行最后一个 fun() ,同理,fun() 的返回值为4。

这样的话,我们再将得到的返回值进行逻辑运算。

answer = fun() - fun() * fun() ;
//  相当于 answer = 2 - 3 * 4  自然就是 -10

answer = fun() + fun() * fun();
//  相当于 answer = 2 + 3 * 4  自然就是 14  

这样我们就清楚了。

总结

我们可以得到这么一条结论:

当语句中存在函数时,会优先执行函数的操作,而后进行运算符的执行。

其实这么说有些果断,片面。 因为当了解数据结构中,运算的实现原理之后,就会明白为什么笔者现在会这么说。 大致来说,运算的实现是又两个“栈”实现的,一个“运算符储存栈”,一个“变量储存栈”。关于这个问题的具体详解,笔者后面会讲到。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值