函数
一个函数至少包括4个部分:
返回值,函数名,参数列表,函数体。
无返回值或者参数时,都用void表示。
void表示空类型,无类型,占一个字节。
用户不能定义一个void类型的变量,但是可以定义void * 类型的指针,可以指向任意数据类型。
函数声明、函数定义,函数调用
函数声明
返回类型 函数名(参数类型1 参数名1,·····,参数类型n 参数名n); //可以只写参数类型,参数名可以省略。
函数声明用来表示函数存在。
函数定义
返回类型 函数名(参数类型1 参数名1,·····,参数类型n 参数名n)
{}//函数的具体实现
函数在具体实现时,一定要判断参数是否符合我们所要处理的数据。防止出现意外。
函数调用
如果函数调用在函数定义前,必须在调用前写函数声明;
如果函数定义在函数调用前面,可以不在调用前写函数声明!
一般情况下,将函数声明放在一起,以便之后管理。
函数定义时的参数,实际上是函数自己定义的属于自己的局部变量,当函数执行完毕,这些变量也随之释放。
所以,函数在传递参数时只能以传值的方式传递的。
例如
void func(int a, int b)
{
int temp = 0;
temp = a;
a = b;
b = temp;
}
int main(void)
{
int x = 3, y = 4;
func(x, y);
}
主函数中的函数调用的参数称为实参,只是将x, y的值传入func()函数中的a, b局部变量,
函数中进行的转换只是将a, b变量的值互换,x和y的值并无改变。
函数调用用是在栈中进行的,栈结构遵循先进后出的原则,因为只有一个口。
调用一个函数时,将目前的状态压在栈下,然后将函数入栈,执行完毕出栈,再继续执行之前的状态。
所以调用函数,使用的是栈内存空间,而栈内存大小是有限的。
在使用递归时,一定要注意递归深度,小心栈满。
带参宏和内联函数
一些语句比较短小,功能比较简单的函数,可以用宏定义实现。
#define MAX(a, b) (a)>(b)?(a):(b)
宏定义只是替换,没有调用开销(栈空间的使用),函数有开销。
函数会检查你的参数列表和返回值类型,而宏定义没有类型,也就不会检查。
如果不想有调用开销,还要检查参数列表可以用内联函数。
内联函数有函数的结构,可以检查参数列表和返回值类型,但是在编译后,却不具备函数的性质。
内联函数不是在调用时发生控制转移,而是在编译时将函数体嵌入在每一个调用处,类似宏替换,使用函数体替换调用处的函数名。
在代码中用inline修饰。
inline void func1(void)
{
printf("hello.\n");
}