深入理解指针1

指针大佬,久仰大名!终于学到你,第一次接触,多多指教哦

1.内存和地址

1.1内存

CPU(中央处理器)在处理数据时,需要的数据是在内存中读取的,处理后的数据也需要再放回内存中,为了高效管理数据,我们会把内存划分为一个个内存单元。

每个内存单元的大小是1个字节(能放8个比特位)。

每个内存单元都有一个编号,我们也成为地址,即内存单元的编号==地址==指针。

1.2如何理解编址

什么是编址?CPU访问内存中的某个字节空间,必须知道这个字节空间在内存中的什么位置,而内存中的字节很多,所以需要给内存进行编址。

计算机中的编址,并不是把每个字节的地址记录下来,而是通过硬件设计完成的。

计算机内有很多硬件单元,这些硬件单元是需要彼此协同工作的,他们之间通过线连起来进行数据传输,同理,CPU和内存之间也需要进行数据传输,所以两者也必须用线连起来。

我们今天重点关注地址总线,我们可以简单理解,32位机器有32根地址总线,每根线只有两态,表示0和1,电脉冲有无,那么一根线就能表示两种含义,2根线表示4种含义,32根线表示2的32次方种含义,每一种含义都代表一个地址。

地址信息被下达给内存,在内存上,就可以找到该地址对应的数据,将数据再通过数据总线传入CPU内寄存器。

2.指针变量和地址

2.1取地址操作符&

在C语言中创建变量,其实就是向内存申请空间。

a是整型数据,int类型占四个字节,此时我们打印的是其第一个字节的地址,但是只要知道了第一个字节的数据,顺藤摸瓜访问到4个字节的数据也是可行的。

2.2指针变量和解引用操作符(*)

2.2.1指针变量

我们通过取地址操作符&拿到的地址是一个数值,比如:0x006FFD70,这个数据有时需要存储起来,供以后方便使用的,我们把这样的地址值存放在指针变量中。

2.2.2如何拆解指针类型

p左边的*是在说明p是指针变量,而前面的int是在说明p指向的是整型int类型的对象。

同理类比,变量是什么类型,变量的地址就要放在什么类型的指针变量中。

eg:char ch='w';

char*pc=&ch;

2.2.3解引用操作符

我们通过取地址符拿到了地址,就可以通过地址找到地址指向的对象,为了找到此对象,我们学习解引用操作符*

老师说运用指针改变变量a写代码就会更加灵活,以后慢慢理解。

2.3指针变量的大小

前面的内容我们提到,32位机器假设有32根地址总线,每根地址线发出来的电信号转换成数字信号后是0或1,那我们就把32根地址线产生的2进制序列当成一个地址,那么一个地址就是32个比特位,需要四个字节才能储存,所以此时指针变量的大小就是4个字节空间。同理如果是64位机器,一个地址就是由64位2进制组成的序列,储存起来就需要8个字节的空间,那么指针变量的大小就是8个字节空间。

x86环境下指针变量的大小都是4个字节,x64环境下都是8个字节

所以指针变量的大小与所指变量类型没有关系

3.指针变量类型的意义

3.1指针的解引用

指针的类型决定了,对指针解引用的时候有多大权限(一次能操作几个字节)

对比这两段代码,在调试中我们可以发现,代码1会将n的四个字节都变成0,而代码2只会将第一个字节变成0.

比如:char*的指针解引用就只能访问一个字节,而int *的指针的解引用就能访问4个字节,short *指针的解引用访问2个字节。

3.2指针加减整数

char*类型的指针变量+1:跳过一个字节

int*类型的指针变量+1:跳过4个字节

指针类型决定了指针向前或向后走一步有多大距离

3.3void*指针

在指针类型中,有一种特殊类型是void*类型,可以理解为无具体类型的指针(也称泛指指针),它可以接受任何类型的地址,但是也有局限性,void*类型的指针不能直接进行+-整数和解引用运算

void类型的指针可以接受不同类型的地址,但是无法直接进行指针运算。

一般void*类型的指针是使用在函数参数部分,用来接收不同类型的数据的地址,这样的设计可以实现泛型编程的效果。

4.const修饰指针

4.1const修饰变量

(const是C语言的一个关键字,可以用来修饰指针)

变量是可以修改的,如果把变量的地址交给一个指针变量,则通过指针变量也可以修改这个变量,但是如果我们想做一些修饰,使变量不能被改变,就要用到const发挥作用。

n本质上还是变量,加入const 我们只是在语法上进行了修饰,所以我们习惯上称n是常变量

但是如果我们绕过n,使用n的地址去改变变量n,这样就打破了语法规则,就可以修改n了。

4.2const修饰指针变量

const修饰指针时,可以放在*左边,也可以放在*右边

  • const如果放在*的左边,eg:int const*p,const int *p,修饰的是指针指向的内容,它可以保证指针指向的内容不能通过指针来改变,但是指针变量本身的内容可变。

  • const如果放在*的右边,修饰的是指针变量本身,保证了指针变量的内容不能修改,但是指针指向的内容可以通过指针改变。

5.指针运算

指针的基本运算有三种:

  • 指针加减整数
  • 指针-指针
  • 指针的关系运算

5.1指针加减整数

因为数组在内存中是连续存在的,使用只要知道第一个元素的地址,就可以顺藤摸瓜找到后面所有的元素。

5.2指针-指针

前提条件:两个指针指向同一块空间。

因为字符串的地址是连续的,所以后面的地址减前面的地址就是字符串长度

指针减指针的绝对值得到的是指针之间的元素个数。

5.3指针的关系运算(其实就是指针/地址的大小比较)

6.野指针

概念:野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)

6.1野指针成因

1.指针未初始化

2.指针越界访问

这里的*(p++)=i,表示每循环一次,就把i的地址存入指针变量p中,而所存数据的内存大小,大过了指针变量p向数组arr申请的内存大小。

3.指针指向的空间释放

6.2如何规避野指针

6.2.1指针初始化

如果明确知道指针指向哪里就直接赋值地址,如果指针不知道指向哪里,可以给指针赋值NULL.

NULL是C语言中定义的一个标识符常量,值是0,0也是地址,这个地址是无法使用的,读写改地址会报错。

初始化为下:

6.2.2小心指针越界

一个程序向内存申请了哪些空间,通贵哦指针也就只能访问哪些空间,不能超出范围访问,超出了就是越界访问。

6.2.3指针变量不再使用时,及时置NULL,指针使用前检查有效性

one rule:只要是NULL指针就不去访问,同时使用指针之前可以判断指针是否是NULL。

6.2.4避免返回局部变量的地址

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值