种一棵树最好的时间是十年前,其次是现在。
大家好这里是笨鸟先飞,最近新学了指针的知识,
为大家带来一篇指针博客的详解。
本篇博客偏基础,适合初学者。
文章目录
前言
在C语言中,指针的使用非常广泛,因为使用指针往往可以生成更高效、更紧凑的代码。总的来说,使用指针有如下好处:
1)指针的使用使得不同区域的代码可以轻易的共享内存数据,这样可以使程序更为快速高效;
2)C语言中一些复杂的数据结构往往需要使用指针来构建,如链表、二叉树等;
3)C语言是传值调用,而有些操作传值调用是无法完成的,如通过被调函数修改调用函数的对象,但是这种操作可以由指针来完成,而且并不违背传值调用。
指针是什么?
指针理解的2个要点
1.指针是内存中一个最小的单元编号,也就是地址
2.平时我们口中所说的指针通常指的是指针变量,是用来存放内存地址的变量
总结:指针就是地址,口语中说的指针通常指的是指针变量
指针变量
我们可以通过取地址操作符,取出变量的内存其实就是地址,把地址存放到一个变量当中,这个变量就是指针变量
代码实例:
int main() { int a = 10;//创建临时变量时,在内存中开辟了一块空间 &a;//我们可以取出她的地址 int* p = &a;//将取出的地址放在变量p里,变量a是整形占4个字节,这里存放的是第一个字节的地址 //这里的*号说明p是一个指针变量,int说明p所指向对象(a)的类型是整形 return 0; }
总结:
- 指针变量,是用来存放地址的变量,(存放在指针中的值都被当作地址处理)。
- 指针是用来存放地址的,地址是唯一标识一块地址空间的
- 一个内存单元的大小是1个字节
- 指针的大小在32位平台上是4个字节,在64位平台上是8个字节
指针和指针类型
我们大家都知道变量是有类型的,那么指针有没有类型呢?
其实是有的
int main() { char* pc = NULL;//为了存放char类型变量的地址 int* pi = NULL;//为了存放int类型变量的地址 short* ps = NULL;//依此类推 long* pd = NULL; float* pz = NULL; double* pm = NULL; printf("%zu\n", sizeof(char*)); printf("%zu\n", sizeof(int*)); printf("%zu\n", sizeof(short*)); printf("%zu\n", sizeof(long*)); printf("%zu\n", sizeof(float*)); printf("%zu\n", sizeof(double*)); return 0; }
运用代码实例为大家讲解指针类型不一样的意义:
通过代码实例与调试想必大家应该理解了,指针类型的意义。
总结:指针的类型决定了指针向前或者向后走一步有多大(距离)
指针的解引用
总结:
- 指针类型决定了指针在解引用的时候访问几个字节
- 如果是int*的指针,访问4个字节
- 如果是char*的指针,访问1个字节
- 以此类推…
野指针
概念:野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
原因
1.局部变量未初始化
#include <stdio.h>
{
int*p; //局部变量的指针没有初始化,意味着*p没有明确的指向
//一个局部变量不初始化的话,放的是随机值是一个不属于我们的地址,
*p=10;//这里如果去访问的话,就是非法访问内存,当我们使用时这里的p就是野指针。
}
2.指针越界访问
#include <stdio.h>
{
int arr[10] = {0};
int*p = arr;
int i = 0;
for(i=0;i<=10;i++)
{
//当指针范围超出数组arr的范围时,p就是野指针
*p=i;
p++;
}
return 0;
}
这里画图实例可以让大家更加理解指针越界访问
3. 指针指向的空间释放
如何避免野指针
1.指针初始化
2.小心指针越界
3.指针指向空间释放即使置NULL
4.避免返回局部变量的地址
5.指针使用之前检查有效性
#include <stdio.h>
{
//当我们不知道p2初始化什么值的时候可以给一个空指针
int* p2 = NULL;
//在使用时
if(p2!=NULL)
{
*p2 = 100;
}
return 0;
}
指针运算
指针±整数
#include <stdio.h>
int main()
{
int arr [10] = {0};
int i = 0;
int sz =sizeof(arr)/sizeof(arr[0]);//求数组的长度
int* p = arr;
for(i=0;i<sz;i++)
{
*p=1;
p++;
//这样就将整个数组的元素都初始化为1
//另外一种写法
//*(p+i)=1;
//跟上面效果一样
}
reutrn 0;
}
这里演示的就是指针加减整数的实例了,大家可以通过图像去理解。
指针-指针
用指针-指针的方法模拟实现strlen函数的实现
#include <stdio.h>
int my_stelen(char* str)
{
char* start = str;//存首元素的地址
while (*str != '\0')
{
str++;
}
return (str - start);
}
int main()
{
int len = my_stelen("abcdef");
printf("%d ", len);
return 0;
}
指针的关系运算
这里其实就是通过画图为大家演示了指针之间的关系运算,大家可以揣摩一下,接下来我把代码简化给大家看看。
这里简化的代码其实在绝大部分的编译器可以跑过去,但是在C语言标准中允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。具体怎么理解呢,还是画图说吧。
指针和数组
数组:数组是一组相同类型元素的集合,在内存中是一块连续开辟的空间
指针变量:指针变量是一个变量,存放的是地址
数组可以通过指针来访问
二级指针
总结:二级指针变量是用来存放一级指针的地址的
指针数组
指针数组是指针还是数组?
答案:是数组。是存放指针的数组。
数组我们已经知道整形数组,字符数组
这是指针数组的应用实例,像存变量一样,指针也可以存放在数组中,然后通过解引用找到下标去访问。
结语
初阶指针讲到这里就要结束了,如果所写内容对你有所帮助的话,别忘了一键三连哦!