指针类型的意义:
1.指针解引用的权限有多大
Void main(){
Int a=0x11223344;
Char *p=&a;
*p=0;
//运行的结果是0x11223300,仅仅把44改变了
}
为什么是改变的44而不是11,这就涉及到计算机存储的两种模式:
大端存储与小端存储。</herf:超链接>
2.指针走的步长
void main(){
Int arr[]={1,3};//首元素地址为0x11
Int *p=arr;
Char *cp=arr;
P+1;//地址变为0x15,一个int走四个字节
Cp+1;//地址变为0x12,而char就走一个字节,利用这个特性,进行强转,很强大
}
野指针以及如何避免野指针:
1.第一种是没有定义的指针,比如
int *p;
*p=20;
这里的指针p的地址是个随机值,你使用的时候并没有申请该地址,如果直接使用该指针,像上面那样赋值,编译器并不会报错,但是会使用未申请的地址,形成错误。//正确的应该让指针初始化,如果不知道该初始化为什么,可以用int *p=NULL;,使用的时候应该使用p=&a,而不是*p=20。
2.被释放掉了
int* text(){
int a=10;
return &a;
}
void main(){
int *p=text();//由于a是个局部变量,所以离开text函数,a就被销毁了,同样是相当于没有申请a的空间
}
3.小心指针越界:在访问数组
数组指针
指针的运算:
指针-指针
void main(){
Int arr[10]={1,2,3,4,5,6,7,8,9,10};
Int *p1=arr[0];//1
Int *p2=arr[9];//10
Int c=p2-p1;
//c=9,指针-指针,得到的结果为俩指针中间的元素个数
}
(占位符1)
使用指针遍历,给数组赋值
Int *vp=NULL;
For(vp=&arr[10];vp>&arr[0];){//先让指针指向数组的第11个地址,尽管没有定义
*--vp=0;//先让指针—指向第十个地址,在修改值
}
指针操作数组
为了方便理解,采用图片形式
这里有一数组为char arr[5]={1,2,3,4,5};
假设数组首元素地址为0x01.
1. char arr[5]={1,2,3,4,5};
2. char(*parr)[5]=&arr;
第二行代码意思是:
parr首先与*结合(因为有括号,按照优先度进行),成为一个指针,再与[5]结合,意味指针指向数组为5个个数的元素。此时parr指向了arr数组
此时parr的数组状态为:(同样假设arr的地址为0x01)
(*parr)- Parr中存放的是整个数组的地址,如果要访问数组元素,应该先把整个数组的地址转换为数组首元素地址即(*parr)
((*parr)+1)-在(*parr)的基础上加1,取到的地址也加1,即取到的为0x02
*((*parr)+1) -对取到的地址0x02进行取值得到值为2
把1换位i,对i遍历便可得到整个数组的内容
其实把char(*parr)[5]=&arr;中的&arr换成arr,效果还是一样的,以parr的视角去看arr这个地址,会把这个地址看作为整个数组的指针,写&arr只是为了方便理解。
此时parr等效于&arr。
&arr是整个数组的地址,arr是数组首元素地址,两者地址相同,
但取一个数组名的地址所产生的是一个指向数组的指针,而不是一个指向某个指针常量值的指针,&arr与arr尽管这两个地址内容相同,但也是有区别的,区别在于类型不同:
&arr类型是地址 arr数组名的类型是指针变量。
如果直接打印printf(“%d”,*(&arr));则打印出来的是printf(“%d”,arr)
我们定义一个指针变量
Char *p=&arr;
这时p赋值的内容为整个数组的地址,但由于将数组的地址赋给了指针变量,指针变量会把它看作数组首元素地址,故可将p看作arr数组名首地址,类型为指针变量。