一、什么是指针
指针描述了数据在内存中的位置,标示了一个占据存储空间的实体,在这一段空间起始位置的相对距离值。在 C/C++语言中,指针一般被认为是指针变量,指针变量的内容存储的是其指向的对象的首地址,指向的对象可以是变量(指针变量也是变量),数组,函数等占据存储空间的实体。
二、指针变量和指针类型
1.指针变量
指针变量是变量。定义一个指针变量,是在内存中开辟一个空间,该空间里面存放地址。
int* pa; // 定义一个指向整型数据的指针变量 int a = 10; int* pa = &a; // 将a的地址赋值给pa
通过指针变量可以进行间接访问和修改所指向的数据,例如:
1.int a = 10; int* pa = &a; *pa = 30; // 修改pa所指向的数据为30,即修改了a的值
2.指针类型
char *pc = NULL; short *ps = NULL; int *pi = NULL; long *pl = NULL; float *pf = NULL; double *pd = NULL;
char*类型的指针是为了存放 char类型变量的地址。 long* 类型的指针是为了存放long类型变量的地址。int*类型的指针是为了存放int 类型变量的地址等等。
三、野指针
野指针就是指针指向的位置是不可知的、随机的、不正确的、没有明确限制的
造成野指针的原因
1.指针未初始化
int *pa;//指针未初始化,默认为随机值 *pa = 30;
2.指针访问越界
int main() { int arr[3][4] = { 0 }; printf("%d", arr[3][4]); return 0; }
3.指针指向的空间释放
int main() { int* p = (int*)malloc(sizeof(int)); free(p); p = NULL; //此处做置空处理或作重新赋值处理,否则会成为野指针 }
四、指针的运算
1.指针加减整数
#include <stdio.h> int main() { int a = 100; int* pa = &a; printf("%p\n", &a); //00AFFADC printf("%p\n", pa); //00AFFADC printf("%p\n", pa + 1); //00AFFAE0 return 0; }
2.指针-指针
两个指针相减代表指针之间所经历的元素数
int My_strlen(const char* a) { char* pa = a; while (*pa != '\0') { pa++; } return pa - a; }
五、指针数组和数组指针
数组指针:是指针,指向数组。例:int (*arr)[10]
指针数组:是数组,数组内容存放的是指针。例:int *arr[10]
1.指针数组
int main(void) { int arr1[3] = { 51,10,1 }; int arr2[4] = { 4,1,6,14 }; int arr3[5] = { 9,9 }; int arr4[2] = { 5,20 }; int* parr[4] = { arr1,arr2,arr3,arr4 }; printf("%d\n", *(parr[0] + 1));//10 printf("%d\n", *(parr[1] + 1));//1 printf("%d\n", *(parr[2] + 1));//9 printf("%d\n", *(parr[3] + 1));//20 return 0; }
int*parr[4]
,因为[ ]
的优先级要比*
要高,所以 parr先与[ ]
结合,构成一个数组的定义,数组名为 parr,而int*
修饰的是数组的内容,即数组的每个元素。也就是说,该数组包含 4 个指向int*
类型数据的指针
2.数组指针
#include<stdio.h> int main() { int arr[3][4] = { {89,65,32,12},{88,65,11,1},{86,51,32,1} }; int(*parr)[4] = &arr; for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { printf("parr[%d][%d]=%d ", i, j, arr[i][j]); } printf("\n"); } return 0; }
对于int(*parr)[4]
,“( )”
的优先级比[ ]
高,*
号和 parr 构成一个指针的定义,指针变量名为arr
,而int
修饰的是数组的内容,即数组的每个元素。也就是说,parr 是一个指针,它指向一个包含 4 个int
类型数据的数组
六、函数指针和指针函数
1.函数指针
函数指针,其本质是一个指针变量,该指针指向这个函数。总结来说,函数指针就是指向函数的指针。 类型说明符 (*函数名) (参数)
#include<stdio.h> int add(int x,int y) { return x + y; } int (*padd) (int,int); //声明函数指针 int main() { padd = &add; //padd函数指针指向add函数 printf("%d",(*padd)(5,1)); return 0; }
2.指针函数
指针函数是返回指针的函数主体是函数,返回值是一个指针
#include<stdio.h> int* Fu(int* i) //传入指针 { int* pi = i; //指针pi指向i return pi; //返回pi指向的地址 } int main() { int a = 10; int* pa = &a; //pa指向a的地址 printf("%d",*fun(pa));//输出pa指向的地址的值 return 0; }
七、二级指针
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里? 这就是二级指针,有了指针变量pa,下面就可以定义二级指针,并对其进行初始化了;定义了二级指针ppa,并通过取地址符获取指针变量pa的内存地址,将其初始化给二级指针ppa
int a = 10; int *pa = &a; int **ppa = &pa;
二级指针的解引用
*ppa **ppa
在ppa前面有两个解引用运算符,第一次解引用后,可访问到指针变量pa,第二次解引用后,便可以访问到变量a了