指针(初阶)

目录

1.指针是什么

2.指针和指针类型

3.野指针

4.指针运算

5.指针和数组

6.二级指针

7.指针数组

1.指针是什么?

指针是什么?

指针理解的2个要点:

1.指针是内存中一个最小单元的编号,也就是地址

2.平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量

总结:指针就是地址,口语中说的指针通常值的是指针变量。

那我们就可以这样理解为:内存

内存 - 电脑上的存储设备4/8/16G或者更高

程序运行的时候会加载到内存中,也会使用内存空间

其实,内存和硬盘是两种完全不同的东西。 说到内存,很多人容易将电脑里面的内存条跟内存卡之类的混淆,其实,电脑里面的内存跟手机运行内存是一样的,它们都是运行内存。 也可以说内存条才是电脑真正的内存,而硬盘是电脑的外存,属于存储设备,内存决非仅仅是起数据仓库的作用。

内存(Memory)是计算机的重要部件,也称内存储器和主存储器,它用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。它是外存与CPU进行沟通的桥梁,计算机中所有程序的运行都在内存中进行,内存性能的强弱影响计算机整体发挥的水平。只要计算机开始运行,操作系统就会把需要运算的数据从内存调到CPU中进行运算,当运算完成,CPU将结果传送出来。

内存的运行决定计算机整体运行快慢。

我们把内存划分为一个一个的小格子,这样的一个小格子称为一个内存单元,一个内存单元的大小为一个字节,这样的内存单元我们给他一个编号,编号相当于地址,地址在C语言又叫指针,这三个东西是一回事。

指针变量

我们可以通过&(取地址操作符)取出变量的内存起始地址,把地址可以存放到一个变量中,这个变量就是指针变量

总结:

指针变量,用来存放地址的变量。(存放在指针中的变量的值都被当成地址处理)。

一个小的内存单元的大小是一个字节。

如何编址?

经过仔细的计算和权衡我们发现一个字节给一个对应的地址是比较合适的。

对于32位的机器,假设有32根地址线,那么假设每根地址线在编址的时候产生高电平(高电压)和低电平(低电压)就是1或者0;

那么32根地址线产生的地址就会是:

0000 0000 0000 0000 0000 0000 0000 0000

0000 0000 0000 0000 0000 0000 0000 0001

0000 0000 0000 0000 0000 0000 0000 0011

......

1111 1111 1111 1111 1111 1111 1111 1110

1111 1111 1111 1111 1111 1111 1111 1111

这里就有2的32次方个地址。

一个byte等于8个bit位,有32个bit位等于4个字节(byte),所以一个地址是4个字节(byte),一个指针就是,个字节。

每个地址标识一个字节,那我们就可以给(2^32byte==2^32/1024kb ==2^32/1024/1024mb==2^32/1024/1024/1024GB==4GB)4G的空间进行编址。

同样的方法,那64位机器,如果有64根地址线,那编址空间是4 * 2^32次方就是16G

根据分析我们明白:

在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节的空间来存储,所以一个指针变量的大小就应该是4个字节。

那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001

..................

1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111

这里就有2的64次方个地址。

一个byte等于8个bit位,有64个bit位等于8个字节,(byte),所以一个地址是8个字节(byte),一个指针就是8个字节。

总结:

指针变量是用来存放地址的,地址是唯一标示一个内存单元的。

指针的大小在32位平台是4个字节,在64位平台是8个字节。

2.指针和指针类型

指针+-整数和指针的解引用

我们都知道,变量有不同的类型,整形,浮点型。那指针有没有类型呢?

其实指针同样也是有类型的。

指针类型其实是有意义的

1.指针类型决定了,指针进行解引用操作的时候,一次性访问几个字节,访问权限的大小

如果是char*的指针,解引用访问1个字节

如果是int*的指针,解引用访问4个字节

如果是float*的指针,解引用访问4个字节

以此类推根据类型的大小决定了指针类型所能访问字节的个数的大小。

2.指针类型决定指针的步长(指针+1到底跳过几个字节)如图:

字符指针+1,跳过1个字节(根据自身类型)

整形指针+1,跳过4个字节(根据自身类型)

指针的类型决定了指针向前或者向后走一步有多远。

3.野指针

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

3.1野指针成因

1.指针为未初始化

p是一个局部指针变量,没有初始化,里边是随机值。

正确写法,p有明确了指向,然后把a的值修改掉了。

2.指针越界访问

3.指针指向的空间释放

其实NULL的真正用法是用来释放动态开辟的空间,这里涉及到了malloc函数。

3.2如何规避野指针

1.指针初始化

2.小心指针越界

3.指针指向空间释放,即使置为NULL

4.避免返回局部变量的地址

因为第一次调用了一次函数栈帧,函数栈帧没有被破坏里面的值没被覆盖,所以打印出来10,

当先调用printf函数的时候,test的函数栈帧被破坏了所以里面的值不再是10了。

5.指针使用之前检查有效性

4.指针运算

  • 指针+-整数
  • 指针-指针
  • 指针的关系运算

4.1指针+-整数

指针加减整数可以访问前后的空间地址。(指针的类型和他保存的地址类型相同的情况下)

4.2指针-指针

注:指针减指针的绝对值,得到两个指针之间的元素个数(这两个指针类型最好相同且在同一块空间上)。

可以用指针减指针求字符串长度:

4.3指针的关系运算

代码简化,这将代码修改如下:

实际绝大部分的编译器是可以顺利完成的,然而我们还是应该避免这样写,因为标准并不保证它可行

标准规定:

允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一元素之前的那个内存位置的指针进行比较。

指针解引用加减也算指针的关系运算

5.指针和数组

1.指针和数组是不同的对象

指针是一种变量,存放地址的,大小4/8字节的

数组是一组相同类型元素的集合,是可以放多个元素的,大小是取决于元素个数和元素的类型的

在内存中它们是呈直线存放的。

2.数组的数组名数组首元素的地址,地址是可以放在指针变量中

可以通过指针访问数组

6.二级指针

指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?

二级指针就是用来存放一级指针的,如下图:

对二级指针解引用:

通过对ppa进行解引用操作*ppa,ppa找到(访问)的是pa,然后再对pa解引用操作*pa,那就能找到(访问)的是a

注:有二级指针,就有三级指针依次类推,不过解引用方法都是一样的,简单来说就是循环嵌套

7指针数组

指针数组是指针还是数组?

答案:是数组。是存放指针的数组

数组我们已知有整形数组,字符数组。

指针数组 - 存放指针的数组

字符数组 - 存放字符的数组

char arr[5];

整形数组 - 存放整体的数组

int arr[10];

用一个指针数组管理三个整形数组:

指针数组的访问方式就相当于二维数组的访问方式*(arr[0] + j)等价于arr[0][j]。

整形指针数组,它的每一个元素都是int*,如果要换成其他类型该成对应的类型即可,列如char*数组它的每一个元素都是char*

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值