whuKK
whuKK
2016-04-07 15:00
采纳率: 50%
浏览 2.6k
已采纳

C语言的陷阱:关于函数参数的“副作用”问题

当我们执行以下代码时:

 int x=1,y=0;   
printf("%d,x=%dy=%d",x=y,x,y) ;

会出现结果:
0,x=0y=0
也就是说在printf语句中由于x=y的影响,x的值被改变了。
但是如果我们写一个函数来完成类似的动作:
定义一个swap函数来交换xy变量的值:

 int  swap(int *a,int *b){
    int t;
    t=*a;
    *a=*b;
    *b=t;
    return 1;
}

之后我们用printf来输出,其中会用到swap函数,我们来看看swap函数的运行是否会影响接下来对xy的输出:

 int main(){
    int x=1,y=0;

    printf("return of swap is %d\tx=%d,y=%d\n",swap(&x,&y),x,y); 
    return 0;
}

上面这段代码的输出如下:
return of swap is 1 x=1,y=0
注意到了么?xy的值并没有交换。
难道swap函数没有执行么?为什么会有返回值呢?
我们再次输出xy的值试试:
在return语句之前增加语句:

 printf("\t\t\tx=%d,y=%d",x,y);

return of swap is 1 x=1,y=0
x=0,y=1
hey,xy的值又交换了!但是出现了延迟。
立即交换和有延时的交换之间的区别是为什么呢?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

5条回答 默认 最新

  • caozhy
    已采纳
     不是什么延迟,而是C语言是从后往前求函数参数的值,并且把值送入了堆栈。
    所以printf("return of swap is %d\tx=%d,y=%d\n",swap(&x,&y),x,y); 
    x y都先被放入了堆栈,然后才执行的swap,x y是复制到堆栈上的,所以再更改它们不会影响堆栈上它们的副本了。
    
    printf("x=%d,y=%d\treturn of swap is %d\n",x,y,swap(&x,&y)); 
    这样写,先执行swap,所以就是交换了。
    
    点赞 评论
  • qq423399099
    小灸舞 2016-04-08 01:33

    楼上正解
    注意printf是从右往左压入参数(压到栈里面),然后再格式化匹配输出,一个个弹栈
    (有点类似经典的printf和++在一起的问题)

    点赞 评论
  • caozhy

    图片说明

    点赞 评论
  • jxhkl
    艾谌 2016-04-18 09:16

    楼上说的对,下面补充一下自己的认识。假设在main函数中x的地址是0x0000 0000; y的地址是0x0000 0004; 当执行
    printf("return of swap is %d\tx=%d,y=%d\n",swap(&x,&y),x,y);函数时,CPU先把参数y复制到堆栈中的一个地址处,假设为0x0000 0008;

    然后CPU再将参数x复制到堆栈中的其它一个地址处,假设为0x0000 000C;然后调用swap函数,而swap函数的参数也是复制main函数中地址在
    0x0000 0000和0x0000 0004处的x,y。当swap函数执行完之后,0x0000 0000处的地址确实变为0,0x0000 0004处的地址也确实变为了1。
    但是当进入printf函数内部进行打印的操作时,printf会取出复制main的放在0x0000 0008和0x0000 000C处的值。也就是1,0.故printf打印出来感觉
    swap没有执行。

    点赞 评论
  • ennaymonkey
    大熊随想 2016-04-21 05:24

    楼上正解
    注意printf是从右往左压入参数(压到栈里面),然后再格式化匹配输出,一个个弹栈
    (有点类似经典的printf和++在一起的问题)

    点赞 评论

相关推荐