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");//返回值 长度7
return 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));//8
for(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));//48
print_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反复看