概念

用一个标签去代表一堆代码,为了复用化 标签–>函数名

返回值 函数名(输入参数){}

  • 函数指针
char *p;
char (*p)[10];

int (*p)(int ,int,char);

函数三要素

函数名 (地址)

定义调用函数

获取函数地址直接调用

int (*myshow)(const char *,...);
printf("HI");
myshow = printf;
myshow("===");

存函数地址的数组

int (*p[7])(int,int);

p[0]=fun0;//注册
p[1]=fun1;
...
//回调
p[day](10,20);

输入参数

承上启下,有输入输出

调用者: 函数名(要传递的数据)//实参 被调者: 函数具体实现 函数返回值 函数名(接收数据)//形参 {xxx}

值传递-普通类型

上层调用者保护自己空间不被修改的能力

int a = 1;
fun(a);
a ?= 1; //true

实参传递给形参

  • 传递的形式:拷贝

地址传递-普通类型

int a = 1;
fun(&a);
a ?= 1://未知

如果想要直接修改原数据则应该传入地址

[!NOTE] eg:

int a;
scanf(%d,a);//有误
scanf(%d,&a);//要对a修改,所以应该这样写,否则a执行完前后不变

作用

  1. 值修改 int * short * long *
  2. 空间传递
    1. 方便子函数直接修改上层空间 const *
    2. 空间传递 char * void *

连续空间的传递-嵌入式中常用

两大因素

  1. 数组
    1. 数组名标签
  2. 结构体
    1. 结构体变量

数组

地址传递

int abc[10];
//实参
fun(abc[10]);
fun(abc);//这样写
//形参
void fun(int *p)
void fun(int p[10])//同上

结构体

类似结构体这样的空间,函数与函数之间的调用方式最好用指针,省空间

struct abc{int a;int b;int c;}
struct abc buf;
//实参
fun(buf);
fun(&buf);
//形参
void fun(struct abc a1)
void fun(struct abc *a2)//节约空间

读写问题

既要避免拷贝浪费内存,又要避免改变传入值可以使用const传入地址

const *p; //只读
//上下二选一
char *p;//可能修改
void fun(const char *p){}

空间分类

结束标志不同,

字符空间

结束标志:内存存放了 0x00(1B),

[!空间操作函数示例]

void fun(char *p){
	int i = 0;
	while(p[i]){
		p[i]...
		i++;
	}
}

[!strlen函数实现]

int strlen(const char *p)
{
	int i = 0;
	/*错误处理,判断输入是否合法*/
	if(p == NULL){
		//return...
	}
	/*内存处理,从头到尾,逐一处理*/
	while(p[i]){
		//功能
	}
}
非字符空间

结束标志:0x00,不能当作结束标志

void fun(unsigned char *p,int len){
	int i;
	for(i=0;i< len;i++){
		p[i]=;a=p[i];//++++++++++
	}
//...
}
  • 对于接收的数据定义为unsigned char
  • 字符以0结尾,若有0则显示不全
  • 使用void表示无类型
send(int sockfd, const void *buf,size_t len,int flags);

recv(int sockfd,void *buf,size_t len,int flags);

对于void传入的数据,使用数组读可能会报错,在函数内部定义一个unsigned char的指针来区出传入的值然后再操作

int fun(void *buf,int len){
	unsigned char *tmp = (unsigned char *)buf;
	tmp[i]//....
}

返回值

基本语法

返回类型 函数名称(输入列表)
{
	return
}

返回类型

基本数据类型 可以返回结构体,但是工程中不建议,返回是拷贝过程,结构体太大费内存,可以返回指针 指针(空间) 不能返回数组

返回基本数据类型

//直接返回值
int fun1(void);
int a=0;
a=fun();
//传入地址返回值
void fun2(int *p);
int a=0;
fun2(&a);a
//直接返回地址
int *fun3(void);
int *p;
p=fun3()
//传入地址返回地址
void fun4(int **p)
int *p;
fun4(&p);

返回连续空间类型

指针作为空间返回的唯一类型 int *fun(); 地址: 指向的合法性 => 不是局部变量

函数内部实现

  1. 静态区,static
  2. 只读区,字符串啥的,基本不用
  3. 堆区,malloc申请的