关于函数调用中参数传递的一些思考

先分析两段代码
//eg1

#include <stdio.h>

int main()
{
    int i=1;
    int a[]={0,1,2,3,4,5};
    scanf("%d %d",&i,&a[i]);
//    scanf("%d %d",&a[i],&i);
    printf("%d/n",a[i]);
    printf("%d/n",a[1]);
    return 0;
}

input:2 4
output:2,4

也许我们希望以第一个输入的i值作为第二个输入的数组元素下标,所以我们希望得到的输出可能是4 1,这里的问题在于:scanf函数的所有参数都在函数被真正调用之前就已经求好值了,所以&a[i]实际上使用的都是i原来的值。如果我们用下面被注释掉的scanf呢?(应该是完全等价的一个替换)

//eg2

#include <stdio.h>

int read(int *ip)
{
    scanf("%d",ip);
    return *ip;
}

void func(int i,int j)
{
    printf("%d/n",i*i);
    printf("%d",j*j);
}

int main()
{
    int val1;
    int val2;
    func(read(&val1), read(&val2));
    return 0;
}


input 4 5
output 25 16
很明显,我们希望的是按顺序输出16 25,而不是25 16,而这里的问题在于:虽然所有的函数实参都是在函数被真正调用之前就已经求好值了,但是注意函数实参的运算次序和实参的入栈次序一样,都是从右到左,所以对于main函数体内的func函数调用,先运算的是read(&val2),输入4,赋值给j(而不是i),然后运算read(&val1),输入5,赋值给i,最后运行func函数体,得到了25 16的非期望输出。

最后我可以得到这个结论:对于一个函数调用的实参,都是在函数被真正调用之前就已经求好值了,对于同一个的多个实参的运算顺序,和函数实参的入栈顺序一样,都是从右到左。

再看一段代码:
//eg3

#include <stdio.h>

int main()
{
    int n=1;
    printf("%d %d/n", n++, n++);
    return 0;
}

编译运行:
vc6下输出:1  1
gcc下输出:2 1
很明显,这不是一种好的习惯,对于n的计算(n++)都是在函数printf被真正调用之前进行的,先处理第二个n++,先取出其值1,在运行n++得到新的n=2,然后处理第一个n++,取出其值2,这样就得到了gcc编译下的输出2 1;而对于vc6编译下的输出1 1,具体有应该如何理解?这里是否可以认为gcc对于标准的支持更好?当然,也许最好的方法是不要写出类似于此类依赖于编译器的代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值