C语言中,指针变量之间的类型转换

Posted by AlstonWilliams on February 17, 2019

注:这篇文章中涉及的很多内容,都跟自己的硬件直接相关,所以,读者如果自行尝试,可能会得到不一致的结果。不过针对本文,一般结果应该是一致的。

在C语言中,类型转换是一件很恼人的事情。我们必须理解到底是如何进行类型转换的,以及各种计算机内部的操作,才能在出现各种稀奇古怪的事件时,做到处之泰然。

一般的变量之间的类型的相互转换,倒也还好说。然而,指针变量之间的类型转换,却有些麻烦。

下面我以一个例子说明,指针变量之间进行类型转换时,其内部到底都发生了什么。

先上代码:

这段代码是干什么用的呢?它会打印出65所对应的ASCII码,也就是”A”.如果只是单纯的想进行这个转换,我们使用普通变量之间的类型转换,就完全足够。这里我们为了了解其指针变量之间的类型转换的过程,所以使用指针来做。

我们首先验证一下结果:

从上图中,我们可以看到,结果确实是”A”。与ASCII码表中一致。

那么其背后到底发生了什么呢?为什么会转换成”A”?

首先,我们都知道,指针变量实际上存储的是内存中的一块地址,也就是说,这里指针变量a实际上c这个变量的地址,假设其逻辑内存地址为0x7ffd0d8824ec,则有下图:

要明白为什么其会被转换成”A”,我们需要了解c这个变量,也就是0x7ffd0d8824ec这个内存地址上,65是如何存放的。在我的机器上,int类型的长度为4,所以65转换成四个字节的十六进制形式为:0x00000041.我们还需要了解机器上,是按小端存储还是大端存储的方式来存储的。在上面的代码中,被注释的那几行就是用来测试机器上的存储方式。这里我得到我机器上的存储方式为小端存储。所以,实际的存储方式如下图:

然后,我们将a这个int类型的指针变量,经过类型转换后,赋值给b这个变量,现在a,b,c三个变量之间的关系,就如下图所示:

指针变量的类型,就好比一个标签,用于读取实际的值时,判断如何进行解析。a这个指针变量,其类型为int,所以其在解析时,会读取0x7ffd0d8824ec之后的四个字节。而b这个指针变量,因为其类型为char,其长度为1个字节,所以其在解析时,会读取地址为0x7ffd0d8824ec这一个字节。

因为是按小端存储的方式,所以b在解析时,读取一个字节,正好读到0x41,其对应的字符就是A.

你可以尝试一下,如果c这个变量的值是321,则b对应哪个字符。答案是,还是A.

从上面的解释中,我们可以看到,关键就在于解析时指针变量的类型的长度,所以,不同类型的指针变量之间,不能胡乱转换,否则会因为类型的长度不一致,出现奇怪的结果。比如,你可以尝试一下,把上面的程序换成char类型的指针变量转换成int类型的指针变量。结果会出乎意料。