空指针

空指针是一类可以指向任何数据类型的指针类型,定义方式为 void* 变量名

int a = 10;
char b = 'A';
float c = 12.432;

void *pA = &a;
void *pB = &b;
void *pC = &c;

怎样把空指针类型强制转换成其他非指针类型? 一开始我想到了这样去做:

int a1 = static_cast<int>(*pA);

这样编译器会报错,正确的方法应该如下:

int a1 = *static_cast<int*>(pA)

指针常量与常量指针

指针常量

int* const PA = &A;  //指针值无法被改变,但指向的资源可以被改变

常量指针

const int* PB = &B;   //指向的资源无法被改变,但可以改变指针

如果我们既不想指针被重新赋值也不想资源被重新赋值,这时只要加上两个const就可以了

const int* const *PC = &C

野指针

野指针时指向一个非法的已经被销毁的内存的指针,会对系统造成不可预估的损害,所以我们应该在指针使用周期结束后及时释放指针所占用的内存。

delete a2; 
a2 = nullptr;//释放地址,删除指针,将无效指针制空

或者我们使用STL中封装好的智能指针来进自动析构指针所占用的内存

指向一维数组的指针

我们定义了一个数组,这个数组名本身就是一个指向数组第一个元素的指针

int a[5] = { 1,2,3,4,5 };

这里a就是一个指针,指向数组内部元素 1,我们可以通过移动其地址来遍历其中的元素

auto *p = a;
cout << *p << endl;   //首地址
cout << *(++p) << endl; //指向下一个地址  每次++都会改变指针变量的值

指针数组:一个存放指针(内存地址)的数组

int* PAArray[3] = { a,&a[1],p };
	for (auto p : PAArray) {
		cout << p << endl;
	}

承接上面的数组a,我们在PAArray中放满了地址

指向二维数组的指针:

指向二维数组的指针有一些复杂,我们定义了一个二维数组如下:

int b[2][3] = { {1,2,3},{4,5,6} };

如果我们像一维数组一样去调用数组名作为指针,如b[0],b[0]+1,假如我们尝试这样去移动指针,得到的只是普通地址的变化

而非元素所在地址.因为b[0],b[1]在这里普通指针

这里我们应该定义行指针来执行相关操作,格式 类型 (* 指针名)[N] = 二维数组

int(*q)[3] = b;

如我们我们像移动一维数组一样移动该指针,指针便会指向每一行元素的第一个元素,遍历方法如下:

for (int i = 0; i < 2; ++i) {
		for (int j = 0; j < 3; ++j) {
			cout << *(q[i] + j) << " ";
		}
	}

练习:分别使用二维数组指针和指针数组来存储字符串:

const char **multiarrayPoinyer = new const char *[3]{ "a","abcd","abcdefg" };
const char(*pArra)[10] = new char[3][10]{ "a","abcd","abcdefg" };

函数指针:

函数指针,顾名思义,就是指向函数的一个指针

格式: typedef 返回值类型  (*指针名)(参数列表....)

举个例子如下:

int sum(int a, int b)
{
	return a + b;
}

typedef int(*PSUM)(int, int);  //通过函数指针类型定义变量
PSUM pSum3 = sum;

但如果函数的返回形式也是函数指针,那该怎么办呢,我们需要定义指向函数指针的指针、

PSUM2 psumttt(int) {   //函数的返回值是上面那个函数指针
	return NULL;
}


int(* (*p)(int))(int);
p = psumttt;