指针常量(常指针):char * const p const位于星号右侧,const修饰指针本身,即指针本身是常量,指针指向地址不可改变,但所指地址变量值可以改变。
常量指针(指向常变量的指针):const char *p cosnt位于星号左边,const修饰指针所指向的变量,即指针本身指向的地址可以改变,但它所指的内容不可以被修改。
指针函数:函数的返回值是一个指针类型。
函数指针:指向一个函数入口地址的指针。
指针数组:它是数组,数组每个元素都是指针。
数组指针:它是指针,指向数组地址的指针。
int *p[n];——指针数组,每个元素均为指向整型数据的指针。
int (*)p[n];——数组指针,指向一维数组的指针。
int *p();——指针函数,函数带回指针,指针指向返回的值。
int (*)p();——函数指针,p为指向函数的指针。
数组指针与指针数组
1. 数组指针定义
//1.先定义数组类型,再定义数组指针变量
typedef int ARRARY[10];
ARRARY *p;
//2.先定义数组指针类型,再定义数组指针变量
typedef int(*ARRARY)[10];
ARRARY p;
//3.直接定义数组指针变量
int(*p)[10];
int arr[10]; //定义数组变量
p = &arr; //赋值
2.指针数组
int *arr[10];
//一维数组做函数参数退化为一级指针,因此需要指定数组大小
//二维数组(多维数组)做函数参数,退化为数组指针
注意arr与arr[0]的区别:arr不能为左值
指针函数与函数指针
如下两个例子
1. int* lpfun(int,int);
2. int (*lpfun)(int,int);
第一种是我们熟悉的指针函数,()优先级比*高,它是函数,返回类型是指针,即函数的返回值为int类型的指针
第二种一定要用括号把*号和lpfun括起来,这种类型与第一种不一样,是指向一种函数地址的指针。这个函数的返回类型是int型,实参也为int型。
函数指针的定义
//1.先定义函数类型,根据类型定义指针变量
typedef int FUN(int a); //FUN函数类型
FUN *p1 = NULL; //函数指针变量
//2.先定义函数指针类型,根据类型定义指针变量
typedef int (*PFUN)(int a);
PFUN p2 = fun; //p2指向fun函数
//3.直接定义函数指针
int (*p3)(int a) = fun; //定义并赋值
int fun(int a) {
//...
}
p = fun; //赋值
p(10); //调用
函数指针的应用
1.函数指针数组与指针数组的结合
//函数指针数组
void(*fun[5])() = { add, minus, multi, divide };
//指针数组
char *buf[] = { "add", "min", "mul", "div" };
for(int i = 0; i < 5; i++) {
if( 0 == strcmp(cmd, buf[i]) ) {
fun[i]();
break;
}
}
- 回调函数
//函数的参数是变量,也可以是函数指针变量
void fun(int x, int y, int (*p)(int a, int b) ) {
//...
p(x, y); //回调函数
}
//好处:新增加的函数可以直接赋值给函数指针变量,原有框架不用改变,可实现多态的特性
#include <stdio.h>
int* lpfun1(int,int); //声明一个返回指针为int类型的函数
int lpfun2(int,int); //普通函数
typedef int (*lpfunPointer)(int,int); //声明一个函数指针类型,用于保存它要指向的函数地址
void main()
{
int *result=lpfun1(10,20);
printf("%d\n",*result);
if(result != NULL) {
delete result; //删除堆中的指针
result = NULL; //使指针无效
}
lpfunPointer p = lpfun2; //保存lpfun2函数的地址,函数名也是一种指针
printf("%d\n", p(12,60)); //调用带参的函数
}
/***********************************************************************************************
lpfun1过程说明:
如果我们在此函数中这样写: int *p=NULL;
*p=x+y;
return p;
这样的写法是错误的,因为在函数中声明的变量在函数执行完后就不存了,即此时p不存了,是个无效指针,就不能得到这个返回值。
而如果在堆中开辟一小内存来存放,并在完成后由手工来释放,则我们可以用int* p=new int;来创建,这样即使函数没了,但
这个p指向的内存还是存在于堆中的,由此我们会看到在main()中用了一个int *result=lpfun1(10,20)把堆中的p指针指向内存的地址赋给result指针,再
手工释放。 这样就不会内存泄露了。
谨记:永远不要从函数中返回局部自动变量的地址。
******************************************/
int* lpfun1(int x,int y)
{
int *p=new int(0);
*p=x+y;
return p;
}
int lpfun2(int x,int y)
{
return x+y;
}