目录
一 const修饰指针及变量(const是场属性——不能改变的属性)
1 const修饰变量
那怎么证明被const修饰的变量本质还是变量呢?
上面我们绕过n,使⽤n的地址,去修改n,我们可以看到这⾥⼀个确实修改了,但是我们还是要思考⼀下,为什么n要被const修饰呢?就是为了 不能被修改,如果p拿到n的地址就能修改n,这样就打破了const的限制(这样做是在打破语法规则),这是不合理的,所以应该让 p拿到n的地址也不能修改n,那接下怎么做呢?这时候就要引入const 修饰指针变量。
2 const 修饰指针变量
2.1种类(四种):
1 int * p; // 没有 const 修饰?2 int const * p; //const 放在 * 的左边做修饰3 const int * p; //const 放在 * 的左边做修饰4 int * const p; //const 放在 * 的右边做修饰5 int const * const p; //const 放在 * 的两边做修饰2和3 意义是⼀样的而两者与4意义是不⼀样的,而5又和234意义不⼀样。
2.2const 放在*的左边做修饰
2.3 const 放在*的右边做修饰
总结:const如果放在*的右边,修饰的是指针变量本⾝,保证了指针变量的内容不能修改,但是指针指向的内容,可以通过指针改变。
2.4const 放在*的两边做修饰
总结:const 放在*的两边做修饰指针指向的内容和指针变量本⾝的内容都不能改变。
二 野指针
1概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)。
2形成原因(1. 指针未初始化、2. 指针越界访问3. 指针指向的空间释放)
# include <stdio.h>int main (){int *p; // 局部变量指针未初始化,默认为随机值*p = 20 ; //非法访问,p就是 野指针return 0 ;}
# include <stdio.h>int main (){int arr[ 10 ] = { 0 };int *p = &arr[ 0 ];int i = 0 ;for (i = 0 ; i <= 11 ; i++){//当指针指向的范围超出数组arr的范围时,p就是野指针*(p++)=i}return 0;}
2.3 指针指向的空间释放
3 如何规避野指针(1 指针初始化、2 ⼩⼼指针越界、3 指针变量不再使⽤时,及时置NULL,指针使⽤之前检查有效性、4 避免返回局部变量的地址。)
2.1指针初始化
方法
2.2⼩⼼指针越界
int main (){int arr[ 10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 };int *p = &arr[ 0 ];int i = 0 ;for (i= 0 ; i< 10 ; i++){*(p++) = i;}// 此时 p 已经越界了,可以把 p 置为 NULLp = NULL ;// 下次使⽤的时候,判断 p 不为 NULL 的时候再使⽤//...p = &arr[ 0 ]; // 重新让 p 获得地址if (p != NULL ) // 判断{//...}return 0 ;}
三 assert 断⾔
1 定义:assert.h 头⽂件定义了宏 assert() ,⽤于在运⾏时确保程序符合指定条件,如果不符合,就报错终⽌运⾏。这个宏常常被称为“断⾔”。
2 语法
assert(p != NULL );
4.1 能⾃动标识⽂件和出问题的⾏号。
# define NDEBUG# include <assert.h>
四 指针传址调⽤
1分类:(分为传值调⽤和传址调⽤)。
2 传值调⽤
你为啥会出现上面结果呢?因为函数传参的本质是实参传递给形参的时候,形参是实参一份临时拷贝,所以对形参的修改,不会影响实参。
3传址调⽤
总结:传址调⽤,可以让函数和主调函数之间建⽴真正的联系,在函数内部可以修改主调函数中的变量;所以未来函数中只是需要主调函数中的变量值来实现计算,就可以采⽤传值调⽤。如果函数内部要修改主调函数中的变量的值,就需要传址调⽤。
本篇文章就到此结束,希望有所能帮到 读者更好的了解指针,后续还会继续更新指针相关识。