1.指针的定义和使用
int point1(){
//定义指针
int a = 10;
//指针定义语法: 数据类型 * 指针变量名
int * p;
cout << "sizeof (int(*)) --> " << sizeof(p) << endl;
//让指针记录变量a的地址 & 取址符
p = &a ;
cout << "指针p为:" << p << endl;
cout << "变量a的地址为:" << &a << endl;
cout << "变量a的值为:" << a << endl;
/**
* 使用指针 通过<br>解引用</br>的方式来找到指针指向的内存
* 指针前加 * 代表解引用,找到指针指向的内存中的地址
*/
*p = 500;
int b = *p;
cout << "变量b的值为:" << b << endl;
cout << "变量a的值为:" << a << endl;
cout << "*p的值为:" << *p << endl;
cout << "变量a的地址为:" << &a << endl;
cout << "变量b的地址为:" << &b << endl;
}
输出:
sizeof (int(*)) --> 8
指针p为:0x16ae5f738
变量a的地址为:0x16ae5f738
变量a的值为:10
变量b的值为:500
变量a的值为:500
*p的值为:500
变量a的地址为:0x16ae5f738
变量b的地址为:0x16ae5f72c
2.指针常量和常量指针
指针常量
特点:指针的指向不能改,指针指向的值可以改 (内存地址不会变,但是内存地址指向的值会改变)
int a = 20;
int b = 30;
cout << "变量a的值:" << a << endl;
cout << "变量a的地址:" << &a << endl;
//指针常量 特点:指针的指向不能改,指针指向的值可以改 (内存地址不会变,但是内存地址指向的值会改变)
int * const p1 = &a;
cout << "指针p:" << p1 << endl; //输出的地址
cout << "指针p:" << *p1 << endl; // 输出地址指向的值
// p1 = &b; //报错,
*p1 = 50;
cout << "指针p:" << p1 << endl; //输出的地址
cout << "指针p:" << *p1 << endl; // 输出地址指向的值
输出:
变量a的值:20
变量a的地址:0x16b303738
指针p:0x16b303738
指针p:20
指针p:0x16b303738
指针p:50
常量指针
特点: 指针的指向可以改,但是指针指向的值不可以改
int a = 50;
int b = 30;
//常量指针 特点: 指针的指向可以改,但是指针指向的值不可以改
const int * p2 = &a;
cout << "变量a的值:" << a << endl;
cout << "变量a的地址:" << &a << endl;
cout << "指针p2:" << p2 << endl;
cout << "指针p2指向的值:" << *p2 << endl;
//*p2 = 100; //报错
p2 = &b;
cout << "变量a的值:" << a << endl;
cout << "变量a的地址:" << &a << endl;
cout << "变量b的值:" << b << endl;
cout << "变量b的地址:" << &b << endl;
cout << "指针p2:" << p2 << endl;
cout << "指针p2指向的值:" << *p2 << endl;
输出:
变量a的值:50
变量a的地址:0x16b06b738
指针p2:0x16b06b738
指针p2指向的值:50
变量a的值:50
变量a的地址:0x16b06b738
变量b的值:30
变量b的地址:0x16b06b734
指针p2:0x16b06b734
指针p2指向的值:30
3.指针数组 --》 是一个数组
指针数组 -- 存放指针的数组
int* arr[3]; // 整形指针的数组
char* arr1[10]; // 字符型指针的数组
4.数组指针 --》 是一个指针
int main()
{
int* p = NULL; // p是整形指针 -- 指向整形的指针 -- 存放整形的地址
char* pc = NULL; // pc是字符指针 -- 指向字符的指针 -- 存放字符的地址
// 数组指针 -- 是不是指向数组的指针? -- 存放数组的地址
int arr[10] = {0,6,0};
printf("数组首元素地址 %p \n",arr);
printf("数组首元素地址 %p \n",&arr[0]);
printf("整个数组的地址 %p \n",&arr);
// 如何存放数组地址呢? &arr 指向整个数组的指针
// 想让 parr 指向整个数组(而不仅仅是第一个元素),你需要声明 parr 为 int (*)[10] 类型的指针。
int (*parr)[10] = &arr;
printf("parr %p\n",parr);
printf("Second element: %d\n", (*parr)[1]); // 通过数组指针访问第二个元素
char pch[10] = {'w','c'};
char (*pch1)[10] = &pch;
printf("Second element: %c\n", (*pch1)[1]); // 通过数组指针访问第二个元素
// 定义一个字符型指针数组
char* pc1[10];
// 字符指针的地址又该如何存放呢?
char* (*pa)[10] = &pc1;
}
下面代码哪个是数组指针?
Int* p1[10]; // 存放指针的数组
Int (*p2)[10]; // 存放数组地址的指针 √
int arr5[10] = {1,2,3,4,5,6,7,8,9,10};
int (*arr5_2)[10] = &arr5;
for (int i = 0; i < 10; i++) {
printf("%d ",(*arr5_2)[i]); // 不太容易理解
}
printf("\n");
// 第二种写法
for (int i = 0; i < 10; i++) {
// *arr5_2 == arr5 ==> 首元素的地址 ==》 arr5_2+i 即表示指针向右移动
printf("%d ",*(*arr5_2+i));
}
printf("\n");
5.函数指针 --》 指向函数的指针
estimate
函数接受一个整数lines
和一个指向函数的指针pf
,这个函数指针指向一个接受int
类型参数并返回double
的函数。
// 函数示例,符合 estimate 的要求
double myFunction(int x) {
return x * 1.5;
}
void estimate(int lines,double (*pf)(int))
{
cout << (*pf)(lines) << endl; // 调用函数指针 pf
}
在
estimate
函数内部,(*pf)(lines)
用于调用函数指针pf
,并将lines
作为参数传递给它。
*pf
是一个函数指针的解引用操作。pf
是一个指向函数的指针,*pf
解引用这个指针,得到指向的函数。例如,如果
pf
是double (*pf)(int)
类型的函数指针,那么*pf
是一个函数,其参数是int
,返回值是double
。你可以用(*pf)(args)
来调用这个函数,传递参数args
。
5.1声明函数指针
函数指针是指向函数的指针,允许你通过指针来调用函数。
// 函数声明
void printMessage();
void anotherFunction();
// 函数定义
void printMessage() {
std::cout << "Hello, World!" << std::endl;
}
void anotherFunction() {
std::cout << "This is another function." << std::endl;
}
// 定义一个函数指针,指向返回类型为 void、参数为无的函数
void (*funcPtr)();
// 指向 printMessage 函数
funcPtr = printMessage;
(*funcPtr)(); // 调用 printMessage
// 指向 anotherFunction 函数
funcPtr = anotherFunction;
(*funcPtr)(); // 调用 anotherFunction
// ------------------
// 第一种写法
typedef int (*ptr1)(int,int);
int Add(int a,int b)
{
int c = a + b;
printf("result is %d\n",c);
}
// 一个函数,接受一个整数和一个回调函数
void process(int value1, int value2,ptr1 callback) {
// 对值进行某种处理
value1 *= 2;
value2 *= 2;
// 调用回调函数
callback(value1,value2);
}
process(5,7,Add);
// 第二种写法
// 指向函数的指针,用于指向一个接受两个 int 参数并返回 int 的函数(例如 Add 函数)
int (*ptr1)(int,int);
// 将函数指针指向 Add 函数
ptr1 = Add;
// 通过函数指针调用 Add 函数
ptr1(5,6);
声明指向某种数据类型的指针时,必须指定指针指向的类型。同时,声明指向函数的指针时,也必须指定指针指向的函数类型。这意味着声明应指定函数的返回类型以及函数的特征标(参数列表)。也就是说,声明应像函数原型那样指出有关函数的信息。例如,假设Pam leCoder编写一个估算时间的函数,其原型如下:
double pam(int)
则正确的指针类型声明如下:
double (*pf)(int)
这与pam()声明类似,这是将pam替换成了(*pf)。由于pam是函数,因此( *pf)也是函数,而如果( *pf)是函数,则pf就是函数指针