指针漫谈
🧨🧧🧨🧧🧨:首先祝大家新年快乐!
一、什么是指针(Pointer)
在计算机科学中,指针(英语:Pointer),是编程语言中的一类数据类型及其对象或变量,用来表示或存储一个存储器地址,这个地址的值直接指向(points to)存在该地址的对象的值。【 维基百科 】
二、我理解的指针
了解磁盘系统的同学可能听说过inode这个东西(这里具体讲了inode),它是Unix文件系统中用来储存文件元信息的东西。
在文件系统中,每个文件对象都对应着一个 inode,其中存储着常用的一些信息(所有者、创建时间、修改时间、文件权限、对应文件对象在系统中存储块的位置等等)
操作系统访问一个文件时分为三个步骤:
通过文件名找到对应的 inode 编号
通过 inode 编号访问对应文件对象的元信息
根据元信息找到文件对应的扇区下对应的数据块,读取数据
🪜 当然了这是简化的流程,实际读取文件比这个复杂一些。还会涉及到内核调用和页缓存等其他操作。
从这个例子可以发现inode像是一种索引,并且会记录用来指向实际的存储数据块的地址。
🍺 这里是不是发现有点像指针了。
三、从Java和Go的角度看指针
1、众所周知Java语言是没有“指针”的。Java虽没有切实的指针类型,但是这个东西是切实存在的。比如Java的引用类型(除了八种基本类型外都是引用类型)实际在存储时都是把引用(堆上的地址)储存在栈,值(对象的数据)储存在堆中。然后通过引用的指向来进行对象数据的读取。(🔥是不是inode指向数据块的思维)
例如:
class Dog { |
由此可见这里面的值传递并不是传递dog本身过去,而是把dog这个引用复制了一份传给change方法。然后change方法拿到引用去找到堆里面的数据进行修改(修改堆数据肯定会影响dog最后的输出),然后dog = null只是把克隆的这个dog引用地址给置空了,完全不影响原dog引用指向堆中。
2、博主也会Go语言,在Go语言中是有指针这个东西的。他是切实存在的类型。Go的世界中new出来的都是指针(Java中new出来的都是“引用”)。这里和Java最大的区别就是Go语言的函数是可以将指针作为参数传入,也可以将引用作为参数传入。看来起比Java更加灵活了。
例如:
package main |
由上面的示例可以发现change1中的参数(dog Dog)实际上就是main中dog的复制品。所以他的内存地址(0xc0000a4030)和main中dog的内存地址(0xc0000a4018)不一致。所以在change1中进行的所有修改都是针对dog(0xc0000a4030)的修改,与main方法的中dog变量没有任何关系。
而change2中的参数是指针类型,它相当于使用了一个指针参数(dog *Dog)来接收0xc0000a4018的值(⚠️ 这里的dog的值是0xc0000a4018,而dog自己又是一个变量所以他自己也有内存地址0xc0000ac020)。所以后续对name和age的操作实际上是针对0xc0000a4018指向的name和age进行操作,与它本身指针变量没有关系。指针变量只有一个属性那就是地址值(0xc0000a4018),这时dog = nil其实是修改了指针变量dog的值(0xc0000a4018)为nil,与main中的dog变量没有关系。所以最后调用change2后依旧输出的是地址:0xc0000a4018 1 name:路玛 age:3。




