第一点:
使用指针三步骤:定义指针变量、给指针变量赋值(绑定指针)、解引用
第一步:定义指针变量
int *p //此处指的是p是指向int类型的指针;
第二步:给指针变量赋值,也就是让指针指向另一个变量,当我们没有指定指针变量之前,这个指针不能被解引用;
p=&a //实现指针绑定,让p指向变量a
p=(int *)4 //实现指针绑定,让p指向地址为4的哪个变量
第三步:解引用
如果没有绑定指针到某个变量就直接解引用,基本一定会出错。
*p=555 //将555放入p指向的变量中
第二点:
野指针是什么
(1)也就是指针被指向的位置是不可知的(随机的、不正确的、没有明确限制的)
(2)野指针运行时可能触发运行时段错误(sgmentation fault)
(3)野指针可能带来三种后果:
指针指向不可访问的内核地址,触发段错误信息,这种算比较好的;
指针指向没什么特别意义的地址空间(譬如我们以前使用过,但是现在已经释放不使用了)这种情况不会报错,不会出现问题,但其实是有问题的;
指针指向了一个正在运行的代码所指向的地址,导致这个变量被离奇的改变,程序出现错误;
如何避免野指针
野指针的错误来源就是指针定义了以后没有初始化,也没有赋值(没有指向一个可用的内存空间),然后去解引用;
解决方法:在解引用之前,一定确保指针指向一个绝对有用的空间;
常规做法:定义指针时,同时初始化NULL;在指针解引用之前,先去判断这个指针是不是NULL;指针使用完之后,将其赋值为NULL;在使用指针前,将其赋值绑定给一个可用的地址空间;

![]()
第三点:
const关键字与指针
const关键字,在C语言中用来修饰变量,表示这个变量是常量。 const只能修饰一个变量;
p与*p是两个变量,因此const修饰可能会理解错误,常见如下:

在某些单片机中,const修饰的变量是不能修改的,但在gcc中,如果骗过编译这块,他是可以改 可以运行的;
第四点:
数组中几个关键符号的理解
前提:int a[10]
a做右值时等同于数组a中首元素的首地址;a不能做左值;
a[0]做左值时代表数组第0个元素所对应的内存空间(连续4字节),做右值时代表第0个元素的值;
&a本质是一个常量,因此不能做左值,做右值时代表的是整个数组的首地址,也等同于&a[0], 结果相同,但是意义不同;
&a[0]字面意思就是数组第0个元素的首地址,做左值时便是数组首元素对应的内存空间,做右值时表示数组首元素的首地址,做右值时&a[0]等同于a;
指针和数组类型匹配的问题:
int *p; int a[5]; p=a; //类型匹配
int *p; int a[5]; p=&a; //类型不匹配
p是int * 类型,&a是整个数组的指针,也就是一个数组指针类型,不是int指针类型,所以不匹配
&a、a、&a[0]从数值上来看相等的,但是意义来看就不同了。从意义上来看a和&a[0]是数组首元素地址,而&a是整个数组的首地址;从类型上来看,a和&a[0]是元素的指针,也就是int *类型;而&a是数组指针,是int(*)[5]类型;
第四点:
指针强制类型转换
说一下我看完这部分知识点之后的感受;指针他妈的真难,看了跟没看一样!!!

先简单做一下我初次看完之后的笔记,后面有感悟再来补。
强制转换过程中,同一类型的数据形式才能够互相转换,不同形式的转换一定出错;
比如整形: int char short long 都是整形的,相互转换可能出错,可能不出错。一般在由占大字节的形式转换小字节的形式时,容易出错,因为会溢出; 由小字节的形式转换为大字节的过程中国不会出错;
不同形式:比如float和int转化一定出错;
第五点:
指针、数组和sizeof运算符、typedef与dpchar
sizeof用来判断当前变量/数据类型在当前环境下占几个字节;
strlen是一个C库函数,用来返回一个字符串长度(字符串长度不计算字符串末尾的“\0”)

数组里面存字符串的时候,在字符最后其实还有一个“\0”所以sizeof(str)的字节长度是6个;

(1)char *p = str; sizeof(p)得到的永远是4,因为这时候sizeof测的是字符指针p本身的长度,和字符串的长度是无关的。
(2)strlen刚好用来计算字符串的长度。
typedef与dpchar

第六点:
指针与函数传参
(1)普通变量作为函数形参
函数传参时,普通变量作为参数时,形参和实参名字可以相同也可以不同,实际上都是用
实参来代替形参;
在子函数内部,形参等于实参,原因是函数调用时把实参的值赋值给了形参;
(2)数组作为函数形参
函数名作为形参传参时,实际传输的不是整个数组,而是数组首元素的首地址(也是这个数组的首地址,因为传参时是传值。所以这两个没区别)。
数组有两个特殊的性质。一是不能复制数组;二是使用数组名字时,数组会自动转化为指向其第一个元素的指针。
可以由整个数组当作函数的参数,也可以由数组中的某个元素当作函数的参数:


所以在子函数内部,传进来的数组名等于是一个指向数组首元素的指针。所以sizeof得到的是4 下面是子函数;

数组作为函数传参时,[]里面的数字是可有可无的,为什么? 因为数组名做形参传输时是个指针,根本没有书写长度这个信息。
(3)指针作为函数形参
和数组作为函数形参是一样的,他指向的是实参的第一个元素的地址,所以形参本身是一个指针!所以打印出他的长度就是指针的长度,为4,具体参考Cplus的293页这个例子

(4)结构体作为函数形参

第七点:
指针中常使人混淆的知识点:
前提是: int a[]; int *p; p=a;
(1)p++; *p
p++是使p指向下一个元素a[1].然后再执行*P,则得到了下一个元素a[1]的值!
(2)*p++
由于*和++同优先级,结合方向为自右向左,因此它等价于*(p++),先引用p的值,实现*p的运算,然后再使p自增1
(3)*(p++)和*(++p)
前者是先用*再加1;后者是先加1再取*;
(4)++(*p)
表示p所指的元素加1;如果p=a,则++(*p)相当于++a[0],若a[0]的值为3,则在执行++(*p)后a[0]的值为4;
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/23247.html