C语言---getmemory指针系列 函数中的传值、传址、引用调用 回调函数

Swap函数的三种传参:传值、传址、引用

int main(){
	int a = 10;
	int b = 20;
	printf("before swap:a=%d b=%d\n", a, b);
	Swap(a, b);
	printf("after swap:a=%d b=%d\n", a, b);
	system("pause");
	return 0;
}

1、传值调用:复制一份值并传入(在swap结束时销毁),不影响原数据

调用方式:	Swap(a, b);

void Swap(int x,int y){
	int tmp=x;
	x=y;
	y=tmp;
}

2、传址调用:将变量的地址交给子函数指针,直接处理这个地址中的数据

调用方式:	Swap(&a, &b);

void Swap(int *x, int *y){
	int tmp = *x;
	*x = *y;
	*y = tmp;
}

3、引用调用

引用,即变量的别名。定义方式:
int a=10;
int &b=a;在这里,意思就是给a变量起了一个新名字b,因此b不可再次被重新定义。
引用在声明时必须初始化,无空引用,并且引用不分等级。

调用方式:	swap(a, b);

void swap(int &x, int &y){
	int tmp = x;
	x = y;
	y = tmp;
}

回调函数

回调函数:别人调用你所写的函数,你只管实现,不管调用。

定义:回调函数就是一个通过函数指针调用的函数。将函数的指针(地址)作为传参传递给另一个函数,这个指针被用来调用其所指向的函数,
作用:
如何使用:

1、回调函数在什么场景有用?
我要在特定时候执行一个任务,至于是什么时候我自己都不知道。比如某一时间到了或者某一事件发生或者某一中断触发。

2、回调函数怎么起作用?
把我要执行的这个任务写成一个函数,将这个函数和某一时间或者事件或者中断建立关联。当这个关联完成的时候,这个函数华丽的从普通函数变身成为回调函数。

回调函数关心的时间or事件or中断触发的时候,回调函数将被执行。
 由一个主题观察判断条件是否满足,满足后会负责调用这个回调函数。

4、回调函数的好处:
 程序变成异步了。也就是你不必再调用这个函数的时候一直等待这个时间的到达、事件的发生或中断的发生(万一一直不发生,你的程序会怎么样?)。再此期间你可以做做别的事情,或者四处逛逛。当回调函数被执行时,你的程序重新得到执行的机会,此时你可以继续做必要的事情了。

1、对普通函数的调用:调用程序发出对普通函数的调用后,程序执行立即【转向被调用函数执行】,直到被调用函数执行完毕后,再返回调用程序继续执行。从发出调用的程序的角度看,这个过程为“调用–>等待被调用函数执行完毕–>继续执行”。

2、对回调函数调用:调用程序发出对【回调函数】的调用后,不等函数执行完毕,立即返回并继续执行。这样,调用程序执和被调用函数同时在执行。当被调函数执行完毕后,被调函数会反过来调用某个事先指定函数,以通知调用程序:函数调用结束。这个过程称为回调(Callback),这正是回调函数名称的由来。

在这里插入图片描述

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
  简单的讲,一般写程序是你调用系统的API,如果把关系反过来,你写一个函数,让系统调用你的函数,那就是回调了,那个被系统调用的函数就是回调函数。
https://blog.csdn.net/zqixiao_09/article/details/50373567
  回调函数不是有该函数的实现方直接调用,而是在特定的事件或者条件发生时由另一方调用的,用于对改时间或者条件进行响应
  回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为一个参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这事一个回调函数。
  用户把一个【函数指针作为参数传递给其他函数】,【后者将“回调”用户的函数】。如果函数可以【在不同的时间执行不同类型的工作】或者【执行只能由函数调用者定义的工作】,都可以使用回调函数。 回调函数无法知道比较的值的类型,所以参数的类型被声明为void*。表示一个指向未知类型的指针。 可以通过函数指针来实现回调函数。一个指向回调函数的指针作为参数传递给另一个函数,后者使用这个指针调用回调函数。
https://www.cnblogs.com/jiangzhaowei/p/9129105.html

int Callback_1() // Callback Function 1
int main()
{
printf("Entering Main Function. ");
Handle(Callback_1);
Handle(Callback_2);
Handle(Callback_3);
printf("Leaving Main Function. ");
return 0;
}

int Callback_1(int x) // Callback Function 1
Handle(a, Callback_1);//带一个参数a

getmemory指针系列

void GetMemory(char *p)//没有任何意义 不能传递动态内存
{
	p = (char *)malloc(100);
	//首先p→&str   后p→malloc申请的内存---------对str没有任何改变
	//没有检测申请是否成功
	// if ( *p == NULL ){...//进行申请内存失败处理}
	//动态创建的内存没释放。
}
void Test(void)
{
	char *str = NULL;
	GetMemory(str);//str始终都是NULL
	strcpy(str, "hello world");//程序崩溃---无法向一个不存在的地址(空指针)写入东西
	printf(str);
}

分析:
1,调用GetMemory( str )后, str并未产生变化,依然是NULL.只是改变的str的一个拷贝的内存的变化
2,strcpy( str, “hello world” );程序运行到这将产生错误。
3,new的时候有可能内存出错,应该在*p = (char *) malloc( num ); 后判断内存是否申请成功,应加上:
if ( *p == NULL )
{
  …//进行申请内存失败处理
}
4,动态创建的内存没释放。

错误分析:
错认为 GetMemory(char *p)中的 p “就是” GetMemory(str)中的str。但p“不是”str,它只是“等于”str 。
就象: int a = 100;
int b = a; // 现在b等于a
b = 500; // 现在能认为a = 500 ?
显然不能认为a = 500,因为b只是等于a,但不是a! 当b改变的时候,a并不会改变,b就不等于a了。 因此,虽然p已经有new的内存,但str仍然是null

GetMemory(str); //把str传进去,str是一个指针,而他实际上是一个int
void GetMemory(char *p) // p是str的一个副本
{
p=(char *)new char[100]; // p的值改变,但是str的值并没有改变。
}
而双重指针为什么就可以了呢:
GetMemory(&str); //把str的地址传进去
void GetMemory(char ** p) // p是str地址的一个副本
{
*p = (char *)new char[100]; // p指向的值改变,也就是str的值改变。
}

修改方法1:(推荐使用这种方法)

void GetMemory2(char **p)变为二级指针.
void GetMemory2(char **p, int num)
{
*p = (char *)malloc(sizeof(char) * num);
}
void Test(void)
{
char *str=NULL;
GetMemory=(&str);
strcpy(str,“hello world”);
printf(str);
}

修改方法2:

char *GetMemory()
{
char *p=(char *)malloc(100);
return p;
}
void Test(void){
char *str=NULL;
str=GetMemory();
strcpy(str,“hello world”);
printf(str);
}

char *GetMemory(void)//返回指向'栈内存'的指针,虽然该指针不是NULL,
					//但栈(动态内容)被释放(清除),现在的内容不可知
		//https://www.cnblogs.com/clover-toeic/p/3736560.html
{
	char p[] = "hello world";//修改为static char p[]
	return p;
}
void Test(void)
{
	char *str = NULL;
	str = GetMemory();
	printf(str);
}
void GetMemory2(char **p, int num)
{
	*p = (char *)malloc(num);//没有搭配free→内存泄漏
							//没有检测malloc是否成功
}
void Test(void)
{
	char *str = NULL;
	GetMemory(&str, 100);
	strcpy(str, "hello");//能够输出hello
	printf(str);
}
void Test(void)
{
	char *str = (char *) malloc(100);
	strcpy(str, “hello”);
	free(str);//1、free(str)之后str变成野指针→if(str != NULL)语句不起作用
	//free将指针指向的内存空间释放掉,但是并没有将指针置为NULL,指针依旧指向那个内存地址
	//并且野指针和空指针不同,野指针有地址,或者说是指向内存,对野指针进行操作,会造成内存错误,
	//并且野指针无法从if语句进行判断其是否为NULL,所以在指针释放之后要将指针置为NULL。
	if(str != NULL)
	{
		strcpy(str, “world”);//篡改动态内存区的内容,后果难以预料,非常危险。
		printf(str);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_42024067/article/details/102530069