1.函数的定义
数据类型 函数名 (【数据类型 形参名,数据类型 形参名, …】)
2.函数的传参
值传递
地址传递
全局变量
3.函数的调用
嵌套调用
递归
4.函数与数组
5.函数与指针
指针函数
函数指针
函数指针数组
函数的定义
#include<stdio.h>
#include<stdlib.h>int main(int argc,char *argv[])
//argc 是计算一共传递参数的个数
//argv 字符指针数组的首地址 输入参数都会保存在这个字符数组里面,最后一个元素是NULL (存放char * 类型的数组)
{printf("argc = %d\n",argc);//for(i = 0;i<argc;i++)for(i = 0;argc[i] != NULL;i++)//等价于上述表达式puts(argv[i]);printf("hello!\n");//返回值 长度7return 0;//当没有返回值时,默认返回最后一条语句的返回值
}
#include<stdio.h>
#include<stdlib.h>
/*
void print_value(void)
{printf("hello world!\n");return ;
}int main()
{print_value();return 0;
}
*/
void print_value(void);
int main()
{print_value();return 0;
}
void print_value(void)
{printf("hello world!\n");return ;
}
//main函数是主调函数,其它被调函数需要写在主调函数上方实现,或者在上方声明才能在下方实现
一个进程的返回状态是给他的父进程看的
值传递
#include<stdio.h>
#include<stdlib.h>int print_value(int a,int b)
{printf("%d %d\n",a,b);return 0;
}int main()
{int i=3, j=5;print_value(i,j);return 0;
}
地址传递 (间接引用)
#include<stdio.h>
#include<stdlib.h>void swap(int *p,int *q)
{int tmp;tmp =*p;*p = *q;*q = tmp;
}int main()
{int i=3, j=5;swap(&i,&j);printf("i = %d,j = %d\n",i,j);return 0;
}
嵌套调用
#include<stdio.h>
#include<stdlib.h>max(int a,int b,int c)
{int tmp;tmp = a > b ? a : b;return tmp > c ? tmp : c;
}
min(int a, int b,int c)
{int tmp;tmp = a < b ? a : b;return tmp < c ? tmp : c;
}
dist(int a,int b,int c)
{return max(a,b,c) - min(a,b,c);
}
int main()
{int a=3,b=5,c=10;int res;res = dist(a,b,c)printf("res = %d\n",res);return 0;
}
递归 一个函数嵌套的调用自己
#include<stdio.h>
#include<stdlib.h>void c(void)
{printf("[%s]begin!\n",__FUNCTION__);printf("[%s]end!\n",__FUNCTION__);
}
void b(void)
{printf("[%s]begin!\n",__FUNCTION__);printf("[%s]call c()!\n",__FUNCTION__);c();printf("[%s]c() returned!\n",__FUNCTION__);printf("[%s]end!\n",__FUNCTION__);
}
void a(void)
{printf("[%s]begin!\n",__FUNCTION__);printf("[%s]call b()!\n",__FUNCTION__);b();printf("[%s]b() returned!\n",__FUNCTION__);printf("[%s]end!\n",__FUNCTION__);
}
int main()
{printf("[%s]begin!\n",__FUNCTION__);printf("[%s]call a()!\n",__FUNCTION__);a();printf("[%s]a() returned!\n",__FUNCTION__);printf("[%s]end!\n",__FUNCTION__);return 0;
}
[main]begin!
[main]call a()!
[a]begin!
[a]call b()!
[b]begin!
[b]call c()!
[c]begin!
[c]end!
[b]c() returned!
[b]end!
[a]b() returned!
[a]end!
[main]a() returned!
[main]end!
递归解决阶乘和斐波那契数列
递归 能够抽象出来一个类似公式的递推
汉诺塔 / 二叉树 /阶乘 /斐波那契数列
#include<stdio.h>
#include<stdlib.h>int func(int n)
{if(n<0)return -1;if(n == 0 || n ==1)return 1;return n * func(n-1);//一层一层的压栈 出栈
}int main()
{int n;int res;scanf("%d",&n);res = func(n);printf("%d! = %d\n",n,res);return 0;
}
#include<stdio.h>
#include<stdlib.h>int fib(int n)
{if(n<1)return -1;if(n ==1 ||n ==2)//已知条件return 1;return fib(n-1) + fib(n-2);//公式
}int main()
{int n;int res;scanf("%d",&n); res = fib(n);printf("fib[%d] = %d\n",n,res);return 0;
}
函数与一维数组
#include<stdio.h>
#include<stdlib.h>
/*
int a[N] = {1,2,3,4,5,6};
int *p = a;//一维数组 a和p除了一个常量一个变量 其他等价
传参形式--->a *a a[0] &a[3] p[i] p *p p+1*(a+0)
函数形参-->int * int int int * int int * int int *
*//*方法一
void print_arr(int *p,int n)
{int i;printf("%s:%d\n",__FUNCTION__,sizeof(p)); for(i =0;i < n;i++)printf("%d ",*(p+i));printf("\n");
}
*/
void print_arr(int p[],int n)//int p[] 形参和定义的时候是不一样的 可以理解一个 [] 等价于一个 *
{int i;printf("%s:%d\n",__FUNCTION__,sizeof(p)); for(i =0;i < n;i++)printf("%d ",*(p+i));printf("\n");
}
void func(int *p,int n)
{int i = 0,m,j,tmp;m = (n-1)/2;for(; i<= m;i++){j = n-1-i;tmp = p[i];p[i] = p[j];p[j] = tmp;}}int main(int argc,char **argv)
//int main(int argc,char *argv[])
{int a[] = {1,3,5,7,9};printf("%s:%d\n",__FUNCTION__,sizeof(a));print_arr(a,sizeof(a)/sizeof(*a));//一维数组传参是传递了数组的起始位置,因此还需要告诉数组的长度func(a,sizeof(a)/sizeof(*a));//逆序数组print_arr(a,sizeof(a)/sizeof(*a));return 0;
}
函数和二维数组
#include<stdio.h>
#include<stdlib.h>
#define M 3
#define N 4
/*
int a[M][N]= {...};
int *p = *a;
int (*q)[N] = a;//数组指针 指向数组的指针 q 也可以称行指针main传参 --> a[i][j] *(a+i)+j a[i]+j p[i] *p q[i][j] *q q P+3 q+2*(q+0)函数定义形参接收--> int int * int * int int int int * int (*)[N] int * int (*)[N]
*/void print_arr(int *p,int n)
{int i;for(i =0;i<n;i++){printf(%4d ",p[i]);//此时,把二维数组当成大的一维数组}printf("\n");
}void print_arr1(int (*p)[N],int m,int n)
//void print_arr1(int p[][N],int m,int n)
{int i,j;printf("sizeof(p) = %d\n",sizeof(p));//8for(i =0;i<m;i++){for(j = 0;j<n;j++)printf("%4d ",*(*(p+i)+j));//printf("%4d ",p[i][j]);printf("\n")}
}float average_score(int *p,int n)
{int i;float sum =0;for(i = 0;i<n;i++)sum += p[i];return sum/n;
}void find_num(int (*p)[N],int num)
{int i;for(i = 0;i < N; i++)printf("",*(*(p+num)+i));printf("\n");
}int main()
{int a[M][N] = {1,2,3,4,5,6,7,8,9,10,11,12};print_arr(*a,M*N);//print_arr(&a[0][0],M*N); //*a a[0] *(a+0) 行指针转换成列指针printf("sizeof(a) = %d\n",sizeof(a));//48print_arr1(a,M,N);//同样需要传递行列数float ave;ave = average_score(*a,M*N);//此时,需求 不需要区分行列 所以按照一个大的一维数组处理printf("ave = %f ",ave);int num = 0;find_num(a,num);return 0;
}
函数与字符数组
#include<stdio.h>
#include<stdlib.h>char *mystrcpy(char *dest,const char *src)
{ char *ret = dest;if(dest! = NULL && src != NULL)while((*dest++ = *src++) != '\0');return ret;
}
char *mystrncpy(char *dest,const char *src,size_t n)
{ int i;for(i = 0;i < n && (dest[i] = src[i]); i++);for(;i <n;i++)dest[i] = '\0';return dest;
}int main()
{char str1[]="helloworld";char str2[128];mystrcpy(str2,str1);mystrncpy(str2,str1,5);puts(str2);return 0;
}
函数与指针关系的详细剖析
指针函数:一个函数的返回值是指针
返回值 * 函数名(形参)
如:int *fun(int);
#if 0
void find_num(int (*p)[N],int num)
{int i;for(i = 0;i < N; i++)printf("",*(*(p+num)+i));printf("\n");
}
#endif
int *find_num(int (*p)[N],int num)//函数的功能越简单越好 和其他函数减少依赖关系
{if(num > M-1)return NULL;return *(p + num);
}
函数指针:指向函数的指针 指向和函数指针相同类型的函数
类型 (*指针名)(形参)
如:int (*p)(int);
#include<stdio.h>
#include<stdlib.h>int add(int a, int b)//函数名是一段代码所关联的入口地址
{return a+ b;
}
int sub(int a,in b)
{return a-b;
}int main()
{int a = 3, b = 5;int ret;int (*p)(int,int);//别忘记括号 指向函数的指针 指向和函数指针相同类型的函数 并通过指针调用函数int (*q)(int,int);//int (int,int) (*q)p = add;q = sub;//ret = add(a,b);ret = p(a,b);printf("%d\n",ret);return 0;
}
函数指针数组:
类型 (*数组名【下标】) (形参)
如:int (*arr[N])(int);
数组中的N个元素 都是指向函数的指针
#include<stdio.h>
#include<stdlib.h>int add(int a, int b)//函数名是一段代码所关联的入口地址
{return a+ b;
}
int sub(int a,in b)
{return a-b;
}int main()
{int a = 3, b = 5,i;int ret;//int (*p)(int,int);//int (*q)(int,int);int (*funcp[2])(int,int);// int (int,int) *funcp[2];//p = add;//q = sub;funcp[0] = add;funcp[1] =sub;//ret = add(a,b);//ret = p(a,b);for(i = 0;i<2;i++){ret = funcp[i](a,b);printf("%d\n",ret);}//printf("%d\n",ret);return 0;
}
p59反复看