先分析两段代码
//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对于标准的支持更好?当然,也许最好的方法是不要写出类似于此类依赖于编译器的代码。
//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对于标准的支持更好?当然,也许最好的方法是不要写出类似于此类依赖于编译器的代码。