指针(1)

 指针的定义

 如何去更好理解指针

 

 如何理解编址

 

 在vs中可以调整机器的位 如当为x86为32位机器 当为x64位时为64位机器  64位机器时地址数量比32位机器地址更多

对于指针本质我们要认识清楚 。编址了解下就行 。

指针变量和地址 

 取地址操作符

 &此时是一个单目操作符,用来取地址,因为地址只能选一个,如果这个变量空间为多个字节,那就取出的是地址较小的字节的地址

指针变量

 答案是char *类型中   (char * pc)

 创建指针变量时*符号在int 和a中间的任何位置都行

放在指针变量中的数据无论是什么 都会被看作是地址 (所以这种情况下如果不是存放地址,放正常的数可能会产生bug) 

在口语中我们把指针变量叫做指针,指针叫做地址  。 跟实际上的不一样

解引用操作符 

 指针变量的大小

 指针变量空间是固定的,无论类型怎么样都是固定的。那这里既然指针类型不影响大小,那么指针类型到底起什么作用呢?这个问题在后续会说到。

指针变量类型的意义

 

指针变量类型的意义:

1.决定解引用操作符访问的权限  

2.在用指针进行计算时其类型会起到很大作用(上文有讲述到作用) 

 

对于存在指针变量里的值需要当作地址看待,所以存入的值要和指针变量的类型一样。如果其类型都是指针类型,只是其存在小差距(一个为char*,一个为int*)编译器会自动帮其转化(会报错,但会正常进行)。如果差距过大,一个为指针类型,一个指针类型都不是,编译器就不能自动帮其转化,系统直接报错不能进行,需要自己动手用强制类型转化操作符。

为了让自己代码不产生任何报错,更加严谨。我们不能让编译器帮我们转化,一旦类型不同,我们就自己用强制类型转化操作符去转化。

&a,&b它们得出的是地址,所以它们类型都是指针类型  (如a是int类型,&a就是int *类型,b是char类型,&b就是char*类型)

void*类型指针

void*类型指针能接受任意类型地址,但与其带来的是不能用*(解引用操作符)进行运算以及用该指针进行牵涉到用到指针类型的计算(因为为void*类型 ,不清楚到底其类型几个字节 ,不能进行牵涉到类型的操作)

 此时void没进行牵涉到类型的操作,所以能正常进行打印出结果。(栈区创建变量由高地址到低地址创建)

至于其真正用途,到后期深入讲指针时会说。

没赋值的变量的处理 (跟本章节所讲东西不关联)

如果是在栈区的变量 ,值完全随机。如果在静态区,默认为0。该知识点后面学到内存管理会有更充足认识。

const修饰 

const修饰变量

对于const它只是对变量的表面进行限制,没改变变量的本质,修饰后依旧是变量,只是不能直接修改被修饰后的变量,如 const int  a=0;,则a就不能再被修改了,但我们能间接通过指针去修改,(因为它限制只是表面进行限制,单纯限制a这个量不能赋值,但没限制其本质内存空间不能改变,所以可以通过其他方式改变其本质内存空间去间接改变a)

 const修饰指针变量

对于const还能修饰指针变量以及*指针变量 

如const   int* a  其就修饰*a   , int  *const  a就修饰a。

其中无需在意const位置,只需记住在*左边修饰*a,在*右边修饰a。

const修饰*a时则是不能通过改变*a改变a所指向的空间内的值。同样可以通过其他方式改变

const修饰a时则是不能通过改变a来改变a的值(跟修饰变量一个道理)。同样可以通过其他方式去改变

const也可以有两个,对*a和a都限制

指针运算 

对于第一种我们已经很清楚具体算法。不讲述

第二种指针-指针计算,其结果是用地址-地址再除以其类型字节大小,所以要实现该计算其前提是两个指针类型要相同,否则不清楚其类型字节大小。 其实质是两指针中间的元素有多少个。

 

对于指针+指针无意义,所以不存在指针+指针 

 

第三种就是指针关系运算,就是直接比大小,没什么特别的 。

野指针 

 野指针定义

野指针其实就是指向了未被申请内存的空间的指针 。

 野指针是极度危险的,我们去使用它,有可能会被当做访问了非法内存从而系统错误。即使没出现上述这种情况,系统能使用这个非法内存,它也是极度危险的,因为它这个空间能再被开辟从而改写里面的数据导致出现异常状况。所以不要出现野指针这种情况。

空指针 

 NUL是个地址且值为0,并且可存入任何类型指针中。存入NULL的指针不可使用,否则会报错,所以存入NULL的指针叫空指针。

 所以对于指针如果你没有确定的地址给它,就给它一个NULL,使其成为空指针,防止其变为野指针,造成无法估计的影响。

同时当我们不再需要使用一个指针时,我们将其指向NULL,这样能避免产生bug(这个是基本书写格式,之后指针都要这样写,显的美观)

 野指针成因

 总而言之这三种情况都是指针访问了未申请的内存空间,从而为野指针。

对于野指针的成因,不只这三种,还有更多原因,随着我们对指针的深入了解会了解到更多野指针成因。但无论有多少,其本质都还是:因为指向了未被申请内存空间,所以成为野指针。

对于未被申请内存的空间如果贸然去使用会造成系统报错,所以尽量别出现野指针这种情况。

如何规避野指针

这里不过多叙述,是规避的方法 ,看下就行,无需详细解释 


assert断言 

 assert其实就是个库函数,所以需要用到头文件 assert.h 。我们通常把assert叫做断言。

assert断言这个函数参数为表达式 ,且为条件判断表达式,如果为真,则不会产生任何作用程序正常进行。如果为假则直接报错,且在弹窗窗口中写入错误的位置地方。

我们还能通过#define  NDEBUG 来控制assert执不执行    (额外想说的#define  e  5  能创造出一个常量e值为5,注意是常量)

 注意在debug版本中assert可以正常使用(在debug版本中可通过define去控制其是否执行)。而在release版本中自带一个#define  NDEBUG,所以默认不执行assert。

我们一般用assert在调试版本去检查代码中的错误,非常方便。

这篇文章有assert的更多细节内容https://blog.csdn.net/weixin_61561736/article/details/124886522

 函数调用

函数调用分为传值调用和传址调用

 函数调用分为传值调用和传址调用   。

传值调用单纯是利用外部的变量,在函数作用时并不会改变函数外部的值。

传址调用可以让函数外部和内部产生真正的联系,在函数内部可以改变外部的值。

如果我们知道其本质,其实很好了解这两个的区别,对于这种我们不能硬记,需要理解其本质。(之前文章提过其本质,这里不过多叙述)

总结 

这就是我对于指针的初步学习,之后还会学习到更多指针的知识,这只是初步的认知,过几天还会发布关于指针的更多知识,敬请期待!谢谢大家!

  • 32
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值