11.华清嵌入式 --函数
一 .函数的基本用法
1.常见的函数
入口函数(main 函数)
库函数(printf scanf等)
2.函数定义,形式
函数完成特定功能的代码模块(代码独立,通常有返回值)
例:double power(double x, int n)
形参 实参 返回值
3.为什么引入头文件?
因为头文件中有函数说明。
4.函数的参数传递
函数的参数传递方式:
全局变量(定义后,程序任何地方均可见)
复制传递方式-值传递(实参传给形参,改变形参不会影响到实参)
地址传递方式(实参为地址,形参为同类型指针)
复制传递使开辟了一个新的空间,不会改变实参的值。
想改变实参的值,可以使用地址传递
想地址传递,但是又不能改变实参,可以加const修饰。(例如求字符串长度)
5.数组在函数间传参
方式:
(1)全局数组的传递方式
(2)复制传递(实参为数组的指针,形参为数组名(本质上是一个指针变量))
int a[] ={5,8,3,4};
int array_sum(int data[])//int *data
{;}
sum =array_sum(a);
一维数组传参需要传数组名,和数组个数(没有结束标志)
字符串数组,可以只传递数组名(可以遍历\0得到长度)
(3)地址传递(实参为数组的指针,形参为同类型指针变量)
二.指针函数(容易出错)
什么是指针函数??
指针函数是指一个函数的返回值为地址量的函数
#include <stdio.h>
char * getstring()
{
char str[20];
strcpy(str,”hello”);
return str;
}
int main()
{
printf(“%s”,getstring());
return 0;
}
找出上面的错误。
- 没有包含#include <string.h>
- str[]为局部变量(栈空间),函数退出时就就回收了,str已经失效。
//变为全局变量,或者使用static修饰(从栈空间到了静态存储区),使用字符串常量也可以
char *str=”hello”这种但是不能修改内容
指针类找错误笔试题,基本出题点都是内存问题(内存有问题,执行结果不确定)
指针函数返回值为:全局变量地址,静态变量地址,字符串常量地址(不能为局部变量)//堆上地址也可以(做了解)
使用指针函数实现删除字符串中的空格
同时理解指针函数的作用。
int main()
{
char str[]=” how are you”;
chat s[50];
strcpy(s,del_stapace(str));//因为有指针函数直接返回返回值,更方便操作
put(s);
return 0;
}
char * del_space(char *s)
{
char *r =s;//保存一下指针的初始地址
char *p =s;
while(*s){
if(*s==’ ’)
s++;
else
{
*p =*s;//将s值赋值给p
s++;
p++;
}
}
*p =’\0’;
}
strcpy 返回值为一个指针,指向目标串起始地址
int m=n=k; //连续赋值
自己实现字符串连接函数(strcat)功能
char *mstrcat(char *dest, const char *src)
{
char *r =dest;
while(*dest != ‘\0’){
dest++;
}
while(*src != ‘\0’){
*dest = *src;
dest++;
src++;
}
*dest = ‘\0’;
return r;
}
以上代码可以简化
char *mstrcat(char *dest, const char *src)
{
char *r =dest;
while(*dest ++);
dest --;//移动到\0之后了,指针需要再回来
while(*dest ++ = *src++);
return r;
}
使用函数 整型转成字符串
char * itoa(char *p,int n) //数据存到*p
{
int r,i=0,j;
while(n)
{
r = n%10;
n/=10; //将整数分开并存到数组中
p[i] = r + ‘0’; //整数和字符串相差48;
i++;
}
p[i] = ‘\0’;
j = i-1;
i =0;
while(i<j){
r=p[i];
p[i] = p[j]
p[j] =r;
i++;
j--;
}
return p;
}
三.递归函数
递归函数是指一个函数的函数体中直接或间接的调用了该函数自身
递归函数调用的执行过程分为两个阶段:
递推阶段:从原问题出发,按递归公式,从未知到已知,最终达到递归终止条件
例:5!= 5*4!=5*4*3!=5*4*3*2!=5*4*3*2*1!=5*4*3*2*1;
回归阶段:按递归终止条件求出结果,逐步带入递归公式,得到结果
例:上面的递归终止条件是1!=1
int fac(int n)
{
if(n==0 || n==1)
return 1;
return n*fac(n-1);
}
思路:寻找递归规律,递归出口(遍历,排序等都有递归的应用)
四.函数指针
函数指针用来存函数地址,这个地址是一个函数的入口地址
形式:
例:
int add(int a,int b)
{
return a+b;
}
int main()
{
int m=10,n =20,k;
int (*p)(int a,int b);//(声明)定义一个函数指针,参数和返回值要和函数对应,a,b可省
p =add;//赋值
k = (*p)(m,n);//函数调函数
}
为什么用??(使差异化的东西更通用化)
假如我们有两个函数
int add(int a,int b){}
int mul(int a,int b){}
int main()
{
int (*p)(int,int);
P =add;
printf(“%d\n”,(*p)(m,n));
p =sub;
printf(“%d\n”,(*p)(m,n));
}
通过修改赋值就能使用不同的函数,很方便。
线程创建(用到了函数指针)
qsort排序函数(也用到了函数指针)
五.函数指针数组
将上面的函数演化一下
int add(int a,int b){}
int mul(int a,int b){}
int main()
{
int (* p[2] )(int,int);
P[0] =add;
printf(“%d\n”,(*p[0])(m,n));
p[1] =sub;
printf(“%d\n”,(*p[1])(m,n));
}
qsort的使用