一. 指针的概念
指针的用途: 高效的访问数据
特征:
高效,简洁(相对于普通变量而言)。
指针可以直接访问物理内存,或者直接操作硬件。(单片机开发)。
内存地址: 计算机需要对物理内存进行管理。因为内存空间大,给每个**存储单元(1byte)**分配一个编号。这个标号就被称为内存地址。

**指针:**就是指针变量。专门用来存储内存地址的变量。在32位系统中,任意类型的指针大小为4byte (0-0xffffffff)。64位系统中任意类型的指针大小为8byte.(0-0xffffffffffffffff).
指针的类型是多种多样:int*(整形的),char*(字符指针),double*(浮点类型指针)。任意类型的指针大小都是一致。 用指针可以表示任意的数据。

相关的运算符:
&:取地址运算符。获得变量在内存空间中的地址编号。
单目运算符,从右向左结合。
被操作对象,只能是变量。不能是常量,或这表达式。
int a =20;
&a; //获得a变量在内存中的地址。需要输出时应使用%p打印地址。
*:解引用操作符。对地址进行解引用操作。
cpp
int main()
{
int a = 66;
char c = 'z';
printf("&a is %p,&a size is %lu\n",&a,sizeof(&a));//整形指针
printf("&c is %p,&c size is %lu\n",&c,sizeof(&c));//字符指针
printf("a = %d\n",*&a);//解引用操作,对象必须是指针
printf("c = %c\n",*&c);
return 0;
}
二. 指针的定义与初始化
cpp
int main()
{
int* pi;//只能指向整形变量的地址
char *pc;//野指针
double *pd = 0;//空指针
float *pf = NULL;//空指针,逻辑上先指向地址为0处的空间,稍后给一个合理的
//地址
int a = 10;
pi = &a;//正常初始化
return 0;
}
注意:1、指针也是有类型的
2、在定义指针时,同时初始化为NULL或者0,防止野指针。
**野指针:成因:**1、指针未初始化,指向的内存地址随机
2、指针指向的变量内存空间被释放
三. 指针的访问
直接访问变量的内容称为直接访问。
使用指针访问变量的内容称为间接访问。
cpp
int main()
{
int a = 0, b = 0, ret = 0;
int *pa = &a, *pb = &b;
printf("input two number:");
scanf("%d %d",pa,pb);
//使用指针完成加减乘除
ret = *pa + *pb;
printf("a + b = %d\n",ret);
ret = *pa - *pb;
printf("a - b = %d\n",ret);
ret = *pa * *pb;
printf("a * b = %d\n",ret);
ret = *pa / *pb;
printf("a / b = %d\n",ret);
return 0;
}
四. 指针的运算操作
cpp
int main()
{
int a = 0, b = 0;
int *pa = &a, *pb = &b;
printf("&a = %p,&b = %p\n",pa,pb);
printf("&a - 1 = %p\n",pa-1);
//pb - pa 指向两个不同变量的指针,相减无意义
//pa = pa * 2, pa = pa / 2 指针的相乘相除都无意义
//
int arr[10] = { 0 };
int *p1 = &arr[0], *p2 = &arr[9];
int ret = p2 - p1;//在同一数组中,指针减指针得到的是两个指针之间的元
//素个数
printf("p2 - p1 = %d\n",ret);
return 0;
}
对于同一数组来说,指针减指针得到的是两个指针之间的元素个数:
相当于:(p1 - p2) / sizeof(基类型)

4.1 不同类型的指针的解引用操作
指针的类型决定了在使用解引用操作时访问几个字节的大小。比如 int* 类型的指针解引用时可访问4个字节,char* 类型的指针在进行解引用操作时可访问1个字节
如果执行*解引用操作话。假设指针存储的地址是0x2000,则不同类型的指针的解引用有如下操作结果:
char*,取0x2000 开始的1个字节空间的数据
int*,取0x2000 开始的4个字节空间的数据
short*,取0x2000开始的2个字节空间的数据
f1oat*,取0x2000 开始的4个字节空间的数据
double*,取0x2000 开始的8个字节空间的数据
4.2 不同类型的指针的++,--
如果执行++。假设指针存储的地址是0x2000,则不同类型的指针的解引用有如下操作结果:
char*,偏移量 1byte -> 0x2001
int*,偏移量 4byte -> 0x2004
short*,偏移量 2byte -> 0x2002
f1oat*,偏移量 4byte -> 0x2004
double*,偏移量 8byte -> 0x2008
五. 大小端存储方式
**大端存储方式:**数据的低字节存储在高地址,高字节存储在低地址
**小端存储方式:**数据的低字节存储在低地址,高字节存储在高地址
大小段存储方式,是由CPU 决定。 51单片机,网络设备,都使用大端方式储存数据。
AMD,intel,ARM,都是采取小端存储。

cpp
int main()
{
int a = 1;
char *p = (char*)&a;//强制类型转换
if(*p == 1)
printf("小端存储\n");
else
printf("大端存储\n");
return 0;
}