赞
踩
第一步:定义指针变量
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关键字,在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用来判断当前变量/数据类型在当前环境下占几个字节;
strlen是一个C库函数,用来返回一个字符串长度(字符串长度不计算字符串末尾的“\0”)
数组里面存字符串的时候,在字符最后其实还有一个“\0”所以sizeof(str)的字节长度是6个;
(1)char *p = str; sizeof(p)得到的永远是4,因为这时候sizeof测的是字符指针p本身的长度,和字符串的长度是无关的。
(2)strlen刚好用来计算字符串的长度。
typedef与dpchar
函数传参时,普通变量作为参数时,形参和实参名字可以相同也可以不同,实际上都是用
实参来代替形参;
在子函数内部,形参等于实参,原因是函数调用时把实参的值赋值给了形参;
函数名作为形参传参时,实际传输的不是整个数组,而是数组首元素的首地址(也是这个数组的首地址,因为传参时是传值。所以这两个没区别)。
数组有两个特殊的性质。一是不能复制数组;二是使用数组名字时,数组会自动转化为指向其第一个元素的指针。
可以由整个数组当作函数的参数,也可以由数组中的某个元素当作函数的参数:
所以在子函数内部,传进来的数组名等于是一个指向数组首元素的指针。所以sizeof得到的是4 下面是子函数;
数组作为函数传参时,[]里面的数字是可有可无的,为什么? 因为数组名做形参传输时是个指针,根本没有书写长度这个信息。
和数组作为函数形参是一样的,他指向的是实参的第一个元素的地址,所以形参本身是一个指针!所以打印出他的长度就是指针的长度,为4,具体参考Cplus的293页这个例子
前提是: 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;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。