文章目录
一、指针的基本概念
地址:用来区分不同内存字节空间的一个编号
指针:指针就是地址,地址就是指针, 地址是一个编号,指针多了指向的概念
1.指针能够让程序更加简洁
2.指针能够让程序更加高效
3.指针提供了一种间接访问变量的方式
二、指针相关运算符
如果*&同时出现,等价于去掉*&运算符后的结果
1、&
&:获得变量在内存空间中的首地址
注意:
1.只能对变量&操作
2.&运算符连接表达式的结果为该变量在内存空间中的首地址
3.&运算符会让类型升级
2、*
*: 左值:将右值放入指针指向的空间
右值:直接取指针对应空间中的值
*p = 100; //左值
*p; //右值
*(p+1); //右值
num = *p; //右值
注意:
1.只能对指针进行 * 操作
2.*运算符能够让类型降级
3.对int * *运算符获得该地址开始向下4字节空间中的值
对double * *运算符获得该地址开始向下8字节空间中的值
对char * *运算符获得该地址开始向下1字节空间中的值
三、指针变量
数据类型 *变量名;
int *p;
double *p;
char *p;
int* 指向4字节空间, double* 指向8字节空间, char* 指向1字节空间
在64位操作系统中,所有指针均占8个字节
野指针:未经初始化的指针或指向已经被释放过空间的指针
注意:
不要使用未经初始化的指针
四、指针初始化
int *p = NULL;
NULL:空指针(指向内存地址为0x0的指针)
int num = 100;
int *p = #
int *p = NULL;
p = #
五、指针算术运算
+
-
++
--
++:向内存高地址偏移指向数据类型大小个字节空间
--:向内存低地址偏移指向数据类型大小个字节空间
两个相同类型的指针相减:获得两个地址中间相差了多少个该类型的元素
六、指针常见操作
int a = 100;
int b = 200;
int *p = NULL;
int *q = NULL;
p = &a;
q = &b;
1、 p = &b;
2、*p = b;
3、 p = q;
4、*p = *q;
1.指针变量本身(p),修改p的值可以改变指针变量的指向
2.指针变量指向的空间(*p),修改*p的值并不能改变指针变量的指向,只是利用指针修改对应空间中的值
七、指针作为函数参数
1.值传递:
实参将值传递给形参,形参改变,实参不会受影响
函数体内想使用函数体外部变量值的时候使用复制传递(赋值传递)
2.地址传递
实参将地址给形参,形参是实参的指针,可以通过对形参取*改变实参的值
函数体内想修改函数体外部变量值的时候使用地址传递
八、指针和数组
int a[5] = {1, 2, 3, 4, 5};
int *p = NULL;
p = &a[0];
p = a;
数组的数组名是指向数组第一个元素的指针常量
a == &a[0]
int *
访问数组下标为n的元素:
a[n] == *(a+n) == *(p+n) == p[n]
指针[偏移量] == *(指针 + 偏移量)
九、二级指针
指向一级指针变量的指针
int **p;
十、void指针
void *p; //所有指针都是8个字节
void * -> int *、char *、double * 不需要强制类型转换
int *、char *、double * -> void * 需要强制类型转换
void * 作为函数参数,可以传入char *、double *、int *的指针,实现一个函数原型下的不同类型指针的传参
十一、const指针
1.const int *p;
2.int const *p;
3.int *const p;
4.const int *const p;
5.int const *const p;
1和2是等价的
const 修饰 *p, p可以改变, *p不能改变
只能使用指针指向的空间数据,不能修改此数据
3
const 修饰 p, p不可以改变, *p可以改变,一定要初始化,否则该指针为野指针
永远指向某个空间的指针(比如数组的数组名)
4和5是等价的
const 修饰p *p, p不可以改变, *p不可以改变,一定要初始化
十二、数组指针、指针数组
1、数组指针
数组指针是指针,指针指向整个数组
数组指针:对一维数组名&,值不变,类型升级为指向整个数组的数组指针
对数组指针*,值不变,类型降级称为指向数组第一个元素的指针
int a[5] = {1, 2, 3, 4, 5};
a可以理解为int *
注意:
在以下两种情况下a不能理解为int *型
1.sizeof操作
2.&操作
&int * == int **
&a == int (*)[5]
2、指针数组
指针数组是数组,数组的每个元素都是指针
int *a[5]:定义一个数组,数组名为a,有5个元素,每个元素为int*型
char *pstr[5];
存放字符串数组用二维数组
操作字符串数组用指针数组
十三、二维数组和指针关系
int a[2][3] = {1, 2, 3, 4, 5, 6};
int *p = NULL;
int (*q)[3] = NULL;
p = &a[0][0];
p = a[0];
p = *a;
q = a;
二维数组的数组名是指向数组第一行所有元素的一个数组指针
二维数组访问第m行第n列元素:
a[m][n];
*(a[m]+n)
*(*(a+m)+n)
*(p+m*N+n)
*(*(q+m)+n)
*(q[m]+n)
q[m][n]
1、二维数组传参
二维数组传递数组指针和长度
char str[5][32] = {0};
int fun(char (*pstr)[32], int len);
2、指针数组传参
指针数组传递二级指针和长度
char *pstr[5] = {"hello", "world", "how", "are", "you"};
int fun(char **ppstr, int len);
十四、指针函数和函数指针
1、指针函数
指针函数是函数,函数的返回值是指针
注意:
不能返回局部变量的地址
2、函数指针
函数指针时指针,指针指向一个函数