变量有地址吗?

变量有地址吗?

学习Go语言在看到这段代码的时候突然一愣,x 被置空了,为什么还有输出?进而引发了我对变量地址和值地址的思考。

func double(x *int)  {
	*x = *x * int(2)
	x = nil
}

func main()  {
	var c int = 2
	double(&c)
	fmt.Println(c)
}

首先什么是变量,在计算机中本来是没有变量的概念的。写汇编或者机器码的同学应该知道,都是直接对内存地址或者寄存器操作。What 变量?你在说什么,我们根本就没有变量。

那变量的概念是从哪儿来的呢?在早期发明计算机以后,大家一开始写的都是用打孔纸带写机器码,后来计算机能力越来越强,大家觉得二进制写着麻烦就发明了一种助记符叫做汇编语言,再后来大家觉得写汇编也麻烦,又基于汇编写了新的高级语言,具有典型代表的就是C语言,从这个时候才出现了变量名的概念。本质上来说,变量名是为了在高级语言中能够把机器代码变得更像人类的自然语言而发明的。但是不要忘了,计算机底层是根本不知道什么变量名的,计算机只知道内存地址。

能够做到这一切当然是编译器的功劳,例如你写了一个 a += 1; 编译器翻译成汇编可能就变成了,add(ECX,1),给寄存器ECX加1(ps:伪代码勿计较)。

后来大家觉得C语言也复杂,又发明了Java,PHP,Go等,那是后话了。

所以,回到开头的问题,变量x有内存地址吗?当然是没有,x只是一个符号,最后提交机器码给CPU执行的时候,编译器早已经把变量地址转换成为了内存地址。

那么,上面的代码 x = nil,是什么意思呢?首先来图解一下

x在代码中是一个指针类型的变量(指针类型是一种变量类型,与int,array等类型平级),它的内存地址存储的值是main函数里面变量c的内存地址。我们用可以用语法 *x 的操作来取变量 c 的值,或者改变变量 c 的值,这就是给我们提供了很多方便的指针操作。但如果直接改变 x 的值,则不会对 c 造成任何影响,只会把 x 的值改变。当然,x 的值改变以后,再使用 *x 就无法再获取或改变 c 的值了。

其实这个问题,在几年前学了了C语言的指针之后就已经可以明白了,但很久不用又忘了。现在再重新来看,又有了比当时更深的理解。

发表评论

邮箱地址不会被公开。 必填项已用*标注