函数指针
函数的分类:
有参数有返回值,无参数无返回值,有参数无返回值,无参数有返回值
区分函数的特征是根据【返回值类型】【参数类型】来确定的
函数名是调用当前函数的重要的名称,同时【函数名是当前指针的指针常量】,
存储当前函数在内存【方法区/函数区】的空间首地址
代码案例
#include <stdio.h>
/*
计算得到两个 int 类型数据之和
@param n1 用户提供的 int 类型数据
@param n2 用户提供的 int 类型数据
@return 两个 int 类型数据之和,返回值数据类型为 int 类型
*/
int add(int n1, int n2);
int main(int argc, char const *argv[])
{
/*
【重点1】
函数的关注点是函数的【返回值数据类型】【形式参数列表数据类型】
【重点2】
函数名是指针常量,存储当前函数在内存【方法区/函数区】首地址
*/
printf("add = %p\n", add);
/*
根据当前函数的【类型】,自定函数指针,存储函数空间首地址
自定义函数指针的格式:
返回值数据类型:
int
形式参数列表数据类型,以及顺序
(int, int) 参数名称不重要!!!
函数指针的名称和固定格式
(* 函数指针变量名称)
小括号包含 * 指针变量标记是为了优化组合关系,如果没有
对应函数返回值数据类型从 int 转换为 int *
可以存储 add 函数空间首地址函数指针变量
*/
int (*pf)(int, int) = add;
/*
pf 就是函数指针,要求
1. 对应函数的返回值数据类型必须是 int 类型
2. 对应函数的形式参数列表必须是(int, int)
*/
/*
函数指针,可以直接当做对应函数使用
*/
int ret = pf(10, 20);
printf("ret = %d\n", ret);
return 0;
}
int add(int n1, int n2)
{
return n1 + n2;
}
函数指针案例
#include <stdio.h> int add(int n1, int n2); int sub(int n1, int n2); int mul(int n1, int n2); int div(int n1, int n2); /* 多功能函数,可以处理用户提供的两个 int 类型数据,处理方式由函数指针 pf 对应的函数决定。 @param n1 用户提供的 int 类型数据 @param n2 用户提供的 int 类型数据 @param pf 处理两个 int 类型数据对应的函数指针,决定当前函数最终功能。 @return 处理数据之后在最终反馈结果。 */ int operation(int n1, int n2, int (*pf)(int, int)); int main(int argc, char const *argv[]) { // shift + Alt + F 对齐代码 int (*pf)(int, int) = NULL; // pf 函数指针指向不同的函数,处理数据的结果不同,执行操作一致 pf = add; printf("ret = %d\n", pf(10, 20)); pf = sub; printf("ret = %d\n", pf(80, 20)); pf = mul; printf("ret = %d\n", pf(30, 20)); pf = div; printf("ret = %d\n", pf(100, 20)); printf("--------------------------------------------\n"); // 调用函数指针作为函数参数的 operation 函数 /* 函数指针作为函数的参数,可以直接提供符合函数指针要求的函数名称 作为实际参数,提供的数据本质是函数在内存【方法区/函数区】的空间 首地址,CPU 可以根据函数指针对应的地址,访问对应的二进制可执行 内存空间内容,执行目标函数 */ int ret = operation(20, 100, add); printf("ret = %d\n", ret); ret = operation(200, 100, sub); printf("ret = %d\n", ret); ret = operation(20, 10, mul); printf("ret = %d\n", ret); ret = operation(1000, 100, div); printf("ret = %d\n", ret); return 0; } int operation(int n1, int n2, int (*pf)(int, int)) { // 函数指针可以直接当前函数使用。 return pf(n1, n2); } int add(int n1, int n2) { return n1 + n2; } int sub(int n1, int n2) { return n1 - n2; } int mul(int n1, int n2) { return n1 * n2; } int div(int n1, int n2) { return n1 / n2; }
内存管理
内存的管理和释放
当程序所需要的空间较大,如果存储在栈区对内存空间特别不友好。此时就可以申请内存空间,存储对应的目标数据内容,利用指针存储对应申请空间的首地址,申请堆区空间之后要通过释放函数释放当前的空间,告知系统当前内存已归还
C 和 C++申请堆区空间的函数
在 C 语言中常用的函数是 malloc、calloc 和 realloc。
1.malloc 函数用于在堆上分配指定大小的内存空间。它的声明如下:
void* malloc(size_t size);
malloc 函数接受一个参数 size,表示需要分配的字节数。如果分配成功,它会返回一个指向分配内存的指针;如果分配失败,返回 NULL。
2.calloc 函数用于在堆上分配指定数量的指定大小的内存空间,并将分配的内存全部设置为零。它的声明如下:
void* calloc(size_t num, size_t size);
calloc 函数接受两个参数 num和 size,分别表示需要分配的元素个数和每个元素的大小。它会返回一个指向分配内存的指针;如果分配失败,返回NULL。
3.realloc 函数用于重新分配已经申请的内存空间的大小。它的声明如下:
void* realloc(void* ptr, size_t size);
realloc 函数接受两个参数 ptr 和 size,其中 ptr 是先前使用 malloc、calloc 或 realloc 返回的指针, size 表示需要重新分配的字节数。它会返回一个指向重新分配内存的指针;如果分配失败,返回 NULL。需要注意的是,realloc 函数可能会在原地或者重新分配内存
C++申请内存空间方式
数据类型 * 数据名 = new 数据类型;
C 语言和C++释放空间函数
C语言释放函数:
void free(void* ptr);
C++ 释放函数
delete 数据名;
创建堆区空间和释放空间操作在明天!
今天分享就到这里啦!!! 我们下次再见!!!