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的值又交换了!但是出现了延迟。
立即交换和有延时的交换之间的区别是为什么呢?

 不是什么延迟,而是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,所以就是交换了。

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

图片说明

楼上说的对,下面补充一下自己的认识。假设在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没有执行。

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