c语言指针
指针变量:存放某个变量的地址
一、指针的定义
int* p;//p的类型是指针,类型名* 指针变量名
p=&a;//&取地址,p存放a的地址,*p和a相同
printf("%p\n",&a);与printf("%p\n",p);结果相同
*解引用操作符,*p找到a的地址
定义多个指针变量时,每个指针变量前面都必须加上*
指针能定义为空指针,但不能定义为某一值。
未初始化的指针变量为随机值,是野指针,指针指向的位置不可知,容易引发严重后果。
野指针的成因
1.指针未初始化
2.指针越界访问
3.指针指向的空间释放
如何规避
1.指针初始化
2.小心指针越界
3.指针指向空间释放及时置NULL
4.指针使用前检查有效性(if(pa!=NULL){
}
所有类型的指针变量所占空间大小都相同,在64位平台的大小是8个字节,在32位的平台的大小是4个字节,不随其他数据类型的改变而改变,但指针类型决定了指针进行解引用操作的时候,能访问空间大小,例
二、基本运算
(*p)++ 即a++,p所指向的变量和*p的值都加1
*p++等价于*(p++),先取*p然后p自加,此时p不再指向a
while 中 * p++ != 'u',是先判断 * p != 'u',然后 p++
&a[i]等价于a[i] a+i等价于*(a+i) p+i等价于*(p+i) &p[i]等价于p[i]
&*p与&a相同,是地址
*&a与啊相同,是变量
相同类型的指针才能相互赋值!
指针变量只能指向与其基类型相同的变量,例:
double *p, *q;
q-p:两个相同类型的指针相减,表示它们之间相隔的存储单元的数目(&arr[9]-&arr[0]=9,但不要两个不同数组相减)
p + 1 / p-1:指向下一个存储单元 / 指向上一个存储单元
其他操作都是非法的,指针相加、相乘和相除,或指针加上和减去一个浮点数
原因(以加法为例):因为指针变量是一种特殊的变量,指针变量的值存放的是所指向变量的地址,两个地址相加并不能保证结果为一个有效的地址值,因而在 C 语言中指针变量相加是非法的
p两个相同类型指针可以用关系运算符比较大小
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较
三、指针作为函数参数
函数参数包括实参和形参,两者类型要一致,可以是指针类型
如果实参是某个变量的地址,相应的形参就是指针变量
在c语言中实参和形参之间的数据传递是单向值传递
要通过函数调用来改变主调函数中某个变量的值:
(1)在主调函数中,将该变量的地址或者指向该变量的指针作为实参
(2)在被调函数中,用指针类型形参接受该变量的地址
(3)在被调函数中,改变形参所指向变量的值
数组名代表一个地址,它的值是数组首元素的地址(基地址)
a+i是数组a的基地址的第i个偏移量
使用指针计算数组元素个数
数组名作为函数参数,在函数调用时,将实参数组首元素的地址传给形参(指针变量),因此,形参也指向实参数组的首元素。如果改变形参所指向单元的值,就是改变实参数组首元素的值。或:形参数组和实参数组共用同一段存储空间,如果形参数组中元素的值发生变化,实参数组中元素的值也同时发生变化。
数组元素作为函数实参时,函数形参为变量,与变量作为函数实参相同,值传递
数组名是指针常量,相当于指针作为函数的参数,数组名做为实参,形参是指针变量(数组),函数调用部分:sum(b) 形参部分int a[]或int* a
四、二级指针
**ppa先通过*ppa找到pa,再对pa解引用操作,找到a
**ppa=30;//等价于*pa=30,等价于a=30
五、指针数组(存放指针)