标签:设计 family 访问 功能 中心 操作 运行 通过 步骤
第33课 - 认清函数的真面目
一.概念
程序 = 数据 + 算法
C程序 = 数据 + 函数
我们下面分析一下汇编语言,汇编语言是从上到下顺序执行的,汇编为了循环执行,就有了跳转指令。通过来回的跳转,就存在了不同的功能模块,这也就是我们C语言中的函数的原型。
模块化程序设计:
C语言中的模块化:
(1) 面向过程是一种以过程为中心的编程思想。
(2) 首先将复杂的问题分解为一个个容易解决的问题。
(3) 分解过后的问题可以按照步骤一步步完成。
(4) 函数是面向过程在C语言中的体现。
(5) 解决问题的每个步骤可以用函数来实现。
二. (函数)声明和(函数)定义
首先声明和定义是不同的。
程序中的声明可以理解为预先高旭编译器实体的存在,如:变量,函数,等等。
程序中的定义明确指示编译器实体的意义。
例如:
// global.c
// int g_var = 0; 定义
#include <stdio.h>
extern int g_var; //声明
void f(int i, int j); /*声明,提前声明,下面的使用就是合法的,否则提前使用不合法。*/
int main()
{
int g(int x);
g_var = 10;
f(1, 2);
printf("%d\n", g(3));
return 0;
}
void f(int i, int j)
{
printf("i + j = %d\n", i + j);
}
int g(int x)
{
return 2 * x + g_var;
}
三. 函数
l 函数参数在本质上与局部变量相同,都是在栈上分配空间。
l 函数参数的初始值是函数调用时的实参值。
例:
#include <stdio.h>
int f(int i, int j)
{
printf("%d, %d\n", i, j);
}
int main()
{
int k = 1;
f(k, k++);
printf("%d\n", k);
return 0;
}
在windows的c++环境中运行的结果是:
1,1
2
在linux的gcc编译器中,运行结果是:
2,1
2
函数参数的求职顺序依赖于编译器的实现。
C语言中大多数运算符对其操作数求值的顺序都依赖于编译器的实现的。
我们看下面一段程序:
int i = f() * g();
到底是f还是g先调用,我们不能确定,在不同的编译器中会有不同的效果。
(1) 程序中存在一定的顺序点。
(2) 顺序点指的是执行过程中修改变量的最晚时刻。
(3) 在程序达到顺序点的时候,之前所做的一切操作必须反映到后续的访问中。
(1) 每个完整表达式结束时。
(2) &&,||,?:,以及都哈表达式的每个运算对象之后。
(3) 函数调用中对所有实际参数的求值完成之后(进入函数体之前)。
下面看一个例子:
#include <stdio.h>
int main()
{
int k = 2;
int a = 1;
k = k++ + k++;
printf("k = %d\n", k);
if( a-- && a ) //左边的是1,右边的是0。
{
printf("a = %d\n", a);
}
return 0;
}
运行结果:6
分析:k = k++ + k++;中分号才是数据点,k++操作是在2的基础上自增,但是这个结果不会瞬间反映到k的值上(因为是后置)。第二个k++也是在2的基础上自增1。在到达数据点之前,k的值会是4。到达分号的时候,我们再完成之前的两次自增的操作,加了两次1,k的值变成6。
改成k = k++ + ++k;或者 k = ++k + k++; 运行结果是7。
改成k = ++k + ++k; 运行结果是8。
C语言会默认没有类型的函数的参数为int。
f(i,j)
{
return i+j;
}
等价于:
f(int i, int j)
{
return i+j;
}
小结:
l C语言是一种面向过程的语言。
l 函数可以理解为解决问题的步骤。
l 函数的实参并没有固定的计算次序。
l 顺序点是C语言中变量改变的最晚时机。
l 函数定义时函数和返回值的缺省类型为int。
标签:设计 family 访问 功能 中心 操作 运行 通过 步骤
原文地址:https://www.cnblogs.com/free-1122/p/9794693.html