1、函数参数
函数参数在本质上与局部变量相同在栈上分配空间
函数参数的初始值是函数调用时的实参值
函数参数的求值顺序依赖于编译器的实现
下面的程序输出什么?为什么?
包括+、-、*、/等等左右操作数谁先计算的顺序c语言并未规定,要根据编译器
3、实例分析
函数参数的求值顺序 44-1.c
- #include <stdio.h>
- int func(int i, int j)
- {
- printf("%d, %d\n", i, j);
- return 0;
- }
- int main()
- {
- int k = 1;
- func(k++, k++);
- printf("%d\n", k);
- return 0;
- }
即先计算的是右边k++
当修改
- #include <stdio.h>
- int func(int i, int j)
- {
- printf("%d, %d\n", i, j);
- return 0;
- }
- int main()
- {
- int k = 1;
- int j = 2;
- func(k++, j++);
- printf("%d\n", k);
- printf("%d\n", j);
- return 0;
- }
可以清晰看到先执行j++,再i++,再call函数
这是常见大多数编译器的执行方式,然而C语言并未规定
对于加减乘除等大多数选择先左操作数,再右操作数4、程序中的顺序点
程序中存在—定的顺序点
顺序点指的是执行过程中修改变量值的最晚时刻
在程序到达顺序点的时候,之前所做的—切操作必须完成
5、C语言中的顺序点
每个完整表达式结束时,即分号处
&&, ||, ?:, 以及逗号表达式的每个参数计算之后
函数调用时所有实参求值完成后(进入函数体之前)
下面的程序运行结束后k的值为多少
6、编程实验
程序中的顺序点 44-2.c
- #include <stdio.h>
- int main()
- {
- int k = 2;
- int a = 1;
- k = k++ + k++;
- printf("k = %d\n", k);
- if( a-- && a )
- {
- printf("a = %d\n", a);
- }
- return 0;
- }
VS2015
当计算2+2后,发现“;”,这是改变内存的最晚时刻,所以对内存
的操作必须完成,即“悬挂的”两个++再计算
当发现&&时,对内存操作必须完成,所以a- -结果为0
在bcc,gcc编译器环境下测试,结果同为6,但不排除其它编译器结果
同样在44-1.c中,两个++操作就在调用函数之前必须完成
在vs2015下编译44-1.c
即编译器先取右k值为1给j,此时一个++”悬挂着”,还未到内存操
作最晚时间,接着,取左边k值为1给i,此时又“悬挂着”一个++,
接着到了内存操作最晚时刻,所以连续两次++,k=3,i=1,j=1
7、小结
函数的参数在栈上分配空间
函数的实参并没有固定的计算次序
顺序点是C语言中变量修改的最晚时机