24.指针-指针和函数-指向函数的指针
24.1 知识点
函数在内存中的存储
我们之前学习了变量的存储。变量是存储在内存中的小房间中的。那么函数是否存储在内存中呢?答案是肯定的,只不过它的存储区域有所不同!
当程序启动时,操作系统会将程序的各个部分(包括代码段、数据段、堆和栈)加载到内存中。在这个过程中,程序中定义的所有函数的机器码(即执行指令)会被加载到代码段中。
代码段
代码段是程序内存中的一部分,专门用于存储可执行代码。它是只读的,防止在执行过程中修改代码。而每个函数在代码段中都有一个入口地址。这个地址指向该函数的第一条指令。函数名在编译时被映射为这个地址,使得我们可以通过函数名来调用函数!
指向函数的指针
指向函数的指针(函数指针)在 C++ 中是一种强大的工具。它允许你通过指针调用函数、实现回调函数、函数数组等功能。
声明语法
返回值类型 (*指针名)(参数类型列表)
例如:
int (*function_ptr)(int, int)
void (*function_ptr)()
注意事项
- 用函数指针指向函数时,函数的返回类型和参数类型必须和函数指针结构上完全一致。
- 函数指针之所以需要用括号把
*
和指针名括起来,是为了区分函数指针和返回指针的函数。 - 函数指针一般指向函数,而指针函数一般指返回类型是指针的函数(之后会专门讲解)。
示例代码
void test()
{
cout << "test函数" << endl;
}
void test2(int a, int b)
{
cout << a << endl;
cout << b << endl;
}
声明一个函数指针,指向一个结构一样的函数:
void (*func11)() = nullptr; //test;
func11 = test;
void (*func12)() = test;
存储了相同的地址,指向test函数:
cout << test << endl; // 00007FF6C2571230
cout << func11 << endl; // 00007FF6C2571230
cout << func12 << endl; // 00007FF6C2571230
隐式地解引用指针并调用函数:
test(); // test函数
func11(); // test函数
func12(); // test函数
显式解引用指针并调用函数:
(*test)(); // test函数
(*func11)(); // test函数
(*func12)(); // test函数
声明一个函数指针,无返回值,有两个参数的:
void (*func2)(int, int) = test2;
func2(11, 12); // 11 12
(*func2)(13, 14); // 13 14
(*func)()
和 func()
有什么区别?
本质上没有任何区别,它们只是写法上的不同。实际上,编译器在编译时会将 func()
自动转换为 (*func)()
。因此,通常我们会选择使用更简洁的写法,直接通过函数指针名来调用指向的函数。
func()
是简洁的语法,它会隐式地解引用指针并调用函数,而 (*func)()
则是显式地解引用指针并调用函数。C++ 编译器允许这两种方式互换,因为它们的含义是完全相同的。
24.2 知识点代码
Lesson24_指针_指针和函数_指向函数的指针.cpp
#include <iostream>
using namespace std;
void test();
void test2(int a, int b);
int main()
{
std::cout << "指向函数的指针\n";
#pragma region 知识点二 指向函数的指针
//声明一个函数指针 指向一个结构一样的函数
void (*func11)() = nullptr;//test;
func11 = test;
void (*func12)() = test;
//存储了相同的地址 指向test函数
cout << test << endl;//00007FF6C2571230
cout << func11 << endl;//00007FF6C2571230
cout << func12 << endl;//00007FF6C2571230
//隐式地解引用指针并调用函数
test();//test函数
func11();//test函数
func12();//test函数
//显式解引用指针并调用函数
(*test)();//test函数
(*func11)();//test函数
(*func12)();//test函数
//声明一个函数指针 无返回值 有两个参数的
void (*func2)(int, int) = test2;
func2(11, 12);//11 12
(*func2)(13, 14);//13 14
// (*func)() 和 func() 有什么区别?
// 本质上没有任何区别,它们只是写法上的不同。
// 实际上,编译器在编译时会将 func() 自动转换为 (*func)()。
// 因此,通常我们会选择使用更简洁的写法,直接通过函数指针名来调用指向的函数。
// func() 和 (*func)() 都是调用 func 指向的函数的方式。
// func() 是简洁的语法,它会隐式地解引用指针并调用函数,而 (*func)() 则是显式地解引用指针并调用函数。
// C++ 编译器允许这两种方式互换,因为它们的含义是完全相同的。
#pragma endregion
}
#pragma region 知识点一 函数在内存中的存储
//我们之前学习了变量的存储
//变量是存储在内存中的小房间中的
//那么函数是否存储在内存中呢?
//答案是肯定的
//只不过它的存储区域有所不同!
//
//当程序启动时,操作系统会将程序的各个部分(包括代码段、数据段、堆和栈)加载到内存中。
//在这个过程中,程序中定义的所有函数的机器码(即执行指令)会被加载到代码段中。
//
//代码段:
//程序内存中的一部分,专门用于存储可执行代码。它是只读的,防止在执行过程中修改代码。
//而每个函数在代码段中都有一个入口地址
//这个地址指向该函数的第一条指令。
//函数名在编译时被映射为这个地址,使得我们可以通过函数名来调用函数!!
#pragma endregion
#pragma region 知识点二 指向函数的指针
//指向函数的指针(函数指针)在 C++ 中是一种强大的工具
//它允许你通过指针调用函数、实现回调函数、函数数组等功能
//声明语法:
//返回值类型 (*指针名)(参数类型列表)
//例如:
// int (*function_ptr)(int, int)
// void (*function_ptr)()
//注意事项:
//1.用函数指针指向函数时,函数的返回类型和参数类型必须和函数指针结构上完全一致
//2.函数指针之所以需要用括号把*和指针名括起来,是用于区分 函数指针 和 返回指针的函数
//3.函数指针一般指 指向函数的指针
// 指针函数一般指 返回类型是指针的函数(之后会专门讲)
void test()
{
cout << "test函数" << endl;
}
void test2(int a, int b)
{
cout << a << endl;
cout << b << endl;
}
#pragma endregion
24.3 练习题
请写出函数指针的声明规则
函数返回值 (*函数指针名)(参数列表)
声明一个返回值为int指针,有三个参数(string、int、float)的函数指针
int* (*func)(string, int, float)
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com