指针的主要作用:提供一种间接访问数据的方法
1.地址:区分不同内存空间的编号
2.指针:指针就是地址,地址就是指针
3.指针变量:存放指针的变量称为指针变量,简称为指针
1.指针的定义
int *p = NULL;
int *q = NULL;
char *p = NULL;
double *p = NULL;
struct student *p = NULL;
野指针:指向随机空间的指针
空指针:指向内存地址为0x0的空间的指针
注意:定义指针一定要初始化,防止成为野指针
2.指针的运算
* : *p作为右值:获得指针指向空间中的值
*p作为左值:将右值放入指针指向的空间
& :获得一个变量在内存空间中的首地址
p+1:向内存高地址偏移指向的数据类型大小个字节空间
p-q:两个地址中间差了多少个指向的数据类型
3.指针数组和数组指针
数组和指针用法的区别:
- 存储数据使用数组
- 操作数据使用指针
数组指针:
对比 int (*a)[5]; 和 int a [5];
int (*a)[5]
:
- 这是一个指针,指向一个包含5个整数的数组。
a
是一个指针,指向一个包含5个整数的数组,可以通过*a
访问这个数组。- 定义一个指针变量 a, 占8个字节空间,指向20个字节空间
int a[5] = {1, 2, 3, 4, 5};
- 这是一个包含5个整数的一维数组。
a
是一个包含5个整数的数组,可以直接通过下标访问数组元素。- 这种声明适用于一维数组,用于存储一组整数值。
int a[5] ={1,2,3,4,5};
a == &a[0] == int *
数组名本质上是一个指向数组第一个元素的指针常量
数组名需要注意的点 : 大部分情况下 a 可以理解为int*型,有2种特殊情况除外
1.sizeof运算时
sizeof(a): 20
sizeof(int *): 8
2.&运算符
&a: int (*)[5]
&int *: int **
数组指针特点:
1.对一维数组,数组名&得到数组指针,值不变,类型升级为指向整个数组的指针
2.对数组指针*,值不变,类型降级为指向数组第一个元素的指针
指针数组
int *a[5];
定义一个数组a,有5个元素,每个元素为int *型,占40个字节空间
char *pstr[5];
操作多个字符串时,通过将每个指针指向一个字符串开头,
完成对所有字符串的操作,使用指针数组
指针数组和二维数组的区别:
存储字符串数组使用二维数组
操作字符串数组使用指针数组
#include <stdio.h>
int main(void)
{
int *p = NULL;
int a[5] = {1, 2, 3, 4, 5};
p = a + 2;
printf("*p1 = %d\n", *p);
p = (int *)(&a + 1) - 1;
printf("*p2 = %d\n", *p);
return 0;
}
运行结果为: