我们学语言的同学们经常说指针指针,很多习题里都有大量指针的巧用,那么指针到底是什么以及指针有什么性质,我们今天就围绕这个展开讲讲。(新人博主希望大家多多点赞,有什么问题也欢迎留言哦)
一、指针是什么
想理解指针,我们需要知道两个要点
1.指针可以泛指内存中一个最小寻址单元的编号
2.平时口语说的指针,通常指的是指针变量是用来存放内存地址的变量。
这里可能很多同学一头雾水:那我也不知道内存是啥?地址是啥啊?
那么我们稍微引入一下计算机组成原理的内容,拿生活中的例子举例吧。
宿舍楼=电脑内存
每个独立的房间=内存里的一个字节
每个房间的门牌号=内存里的一个字节的地址
写着房间门牌号的小纸条=严格意义上的指针
所以这里给你一些肯定不会错的结论,
- 一个指针只对应一个字节
- 一个指针的长度取决于机器类型,即32位机器的指针就是32位的长度即4个字节,64位机器的指针就是64的长度即8个字节。(这是一种不太准确的说法但是初学者理解成这样就足够)
- 严谨来说,在实模式无虚拟内存时,指针长度=MAR长度=地址总线长度。
- 易错易混:32位机器的指针就是32位的长度即4个字节 32位机器的地址写的是八位十六进制他们之间的关系是 4×8=32
=
二、指针和指针类型
变量有不同的类型,如整型浮点型等等。那么指针有没有不同的类型呢?有的兄弟有的。
和变量类似:
char*类型的指针是为了存放char类型变量的地址
int*类型的指针是为了存放int类型变量的地址
short*类型的指针是为了存放short类型变量的地址
指针类型有什么用呢
1.指针类型决定了对指针解引用的时候有多大的权限,如图:


都是对指针解引用赋0,为什么结果会不同呢?
本例当中采用的是32位模拟器所以一个地址对应四个字节这个地址当中的存放是
44 33 22 11
低————>高
两位十六进制对应一个字节
可以看到当指针类型为int*的时候a直接变为0
但是当指针类型是char*的时候是287453952这是十进制他的十六进制是11223300
发现了吗?char*只改变了一个字节,而int*改变了四个字节
有的同学到这又要问了欸你不是说一个指针对应一个字节吗?
没错,但这是两个不同的点
指针本身:只指向一个字节(只存一个地址)
指针类型:决定从这个字节开始一共用多少个连续字节
所以不是指针只能用一个字节,而是一个指针永远只盯死一个起始字节
2.指针的类型决定指针向前或者向后一步有多大

可以很明显的看到
字符指针加一往前加了一
整形指针加一往前加了四
三、野指针
野指针就是指针指向的位置不可知的(随机的,不正确的,没有明显限制的)
1.野指针成因
指针未初始化
指针越界访问(比如指针指向的范围超过数组arr的范围时)
指针指向的空间被释放了(比如函数开辟的临时空间)
2.如何规避?
指针初始化
防止指针越界
指针指向的的空间释放及时null
避免返回局部变量的地址
指针使用之前检查其有效性
四、指针运算
1.指针加减整数
这个很简单,就是字面意思,如果你是整形指针那么你加一,就往后跳一个整形。比如
int arr[3] ={1,2,3};
int*p=arr;
*p=*p+1;
printf("%d",*p);
这个时候打印出来的就是2,相应的你如果是字符指针你加减一就会在对应的字符上往前或者往后一位。
2.指针加减指针
这里我们在学习指针之前在函数那一块的时候我们可能碰到说让你不许用strlen去求解一段字符串的长度我们当时的做法是这样的:
#include<stdio.h>
//int my_strlen(char* arr) {
//int b = 0;
//while (*arr !='\\0') {
////字符串的末尾是\\0斜杠不要写反了
//b++;
//arr++;
//}
//return b;
//}
int my_strlen(char* arr) {
if (*arr == '\\0') {
return 0;
}
else
return 1 + my_strlen(arr + 1);
}
int main() {
char arr[] = "abcd";
int a = my_strlen(arr);
printf("%d", a);
return 0;
}
但是在我们学习了指针之后我们可以充分利用指针的特性。什么特性呢?
即,指针减指针等于两个指针之间的元素个数
#include<stdio.h>
int my_strlen(char* arr) {
char* p = arr;
while(*p != '\\0') {
p++;
}
return p – arr;
}
int main() {
char arr[] = { "abcdef" };
int ret = my_strlen(arr);
printf("%d", ret);
return 0;
}
3.指针的关系运算

这两段代码看似相同实则第二段代码会在一些编译器上报错,要注意标准规定
5.指针和数组的关系
数组名表示数组首元素的地址。
所以,如果*p=arr,那么*(p+i)=arr[i]
那么我们完全可以再大胆一点,
arr[i]=*(arr+i)=*(i+arr)=i[arr]
是不是恍然大悟?
发现哦~原来他真的是个指针啊!
嗯对主播也很震惊,所以你以后打印arr[i]的时候完全可以写成i[arr]当然不太标准,
这里只是为了让你加深理解所以这么讲。
六、二级指针
来,指针是不是就是一个变量的地址?
二级指针就是一个变量地址的地址(指针变量也是变量嘛~)
简单吧?这个地方也得注意写法哦

七、指针数组
字符数组,整型数组这两个都是数组,那指针数组呢?
当然也是数组啦~
int*arr[5]
这样写。
欸等等,那我是不是可以用这个指针数组去搞一个二维数组出来?!
可以的
下一节写,欸嘿



