1.函数调用
1.使用形式
函数调用前必须先定义
实参个数与形参个数需要匹配
实参与形参类型不一致时,会将实参类型转换为形参类型
函数的调用过程 #include <stdio.h> void fun3() { printf("this is fun3...\n"); return ; } void fun2() { fun3(); printf("this is fun2...\n"); return ; } void fun1() { fun2(); printf("this is fun1...\n"); return ; } int main() { fun1(); printf("this is main...\n"); return 0; }原理如下:
2.函数参数的传递
2.1值传递
实参把参数数据的内容通过赋值运算符给形参的形式。形参是实参的一个副本(复制品)。数据内容是相同的,但实参的内存空间和形参的内存空间是独立的。 没有办法通过修改形参来达到修改实参的目的。值传递只能读取实参的值,不能进行修改。
#include <stdio.h> void fun(int arg) { arg++; printf("fun arg:%d\n",arg); } void swap(int a,int b) { int t = 0 ; t = a; a = b; b =t; printf("swap a:%d b:%d\n",a,b); } int main() { int i =10; fun(i); printf("i:%d\n",i); int a = 20; int b =1; swap(a,b); printf("main a:%d,b:%d\n",a,b); return 0; }原理如下:
2.2地址传递
实参传递变量的内存地址值。 既可以读实参的数据的值,也可以修改。
一维整形数组做参数本质是地址传递。
void fill_array(int a[],int size)// int [] a; // 如果是整形数组的化,还需要数组的大小 { // 如果实参是数组类型,在被调内部,会降级为指针( 8 byte ,是数组在内存中的一个编号) // int size = sizeof(a)/sizeof(a[0]); int i = 0 ; for(i=0;i<size;i++) { // 这个不是值传递, 所以可以修改数组。 a[i] = rand()%30; } // printf("sizeof is a %lu\n",sizeof(a)); // printf("sizeof is a[0] %lu\n",sizeof(a[0])); } int main() { srand(time(NULL)); int array[10]={0}; int size = sizeof(array)/sizeof(array[0]); fill_array(array,size);// int [] return 0; }一维字符数组的传参本质也是地址传递
// 对于字符数组(字符串)而言, 约定以\0 结尾。 // 所用可以通过判断\0 的位置,可以得出字符串的长度。 // 所以不需要传入 size int mystrlen(char a[]) // 依然是地址传递,可以对数组对写操作 { // sizeof(a) == 8byte int len = 0 ; while(1) { if('\0'!=a[len]) { len++; } else { break; } } return len; } int main() { char str[100]={0}; // char [] printf("input string1:"); gets(str); // hello\0 int len =mystrlen(str) return 0; }3.函数的递归
3.1定义
在函数内部自己调用自己的函数调用被称为函数的递归。函数的递归属于循环的一种表现形式。 区别是函数的递归会使用栈空间。
此处需注意的是:需要设置合理的退出条件且递归的层次不要太深,太深会消耗大量的内存,可能导致程序崩溃。
示例:5的阶乘
int fun(int n) { if(1 == n || 0==n ) { return 1; } else { return fun(n-1) * n; } } int main() { int ret = fun(5); printf(" 5的阶乘 %d\n",ret); return 0; }原理如下: