指针是c语言的灵魂,而数据的强制转换是我们在写程序的过程中经常去使用的一种手段,那么这二者结合在一起后会有什么效果呢?
直接上例子说吧
No.1
上面是一段简单的把变量打印出来的程序,显示指针指向地址的值,就不多介绍了。下面我们加上几行程序:
我们知道,char类型是带符号的,所以这边我们先定义一个初始值为-100,打印出来的值也是正确的-100,这是我们额外定义一个unsigned char指针类型的指针变量,然后把char指针的变量强制转换后赋给unsigned 插入类型的指针变量,再打印出这块地址的变量的值,和上面不一样了。
当然会不一样,unsigned char都说了是无符号,所以肯定不会打印负的数出来。那么为什么明明是同一块地址,打印出来的值会不一致呢?
我们知道,数据在计算机中存储的形式是二进制,也就是说是一串由1和0组成的数据,char类型,那么就是8位,而-100,这串数据就是 10011100 。也就是说上面这串数据被存储在计算机中,并且被打上了char的标签,那么我们在调用的时候,计算机会用char的方式去解读 10011100 这串数据,也就是为什么会打印出-100了。
而这时候,我们将char的指针变量强制转换后赋值给unsigned char的指针变量,说明什么,说明我新建了一个指针变量去指向这块地址并且打上了unsigned char这个标签,那么我下一次去调用这个指针变量c的时候,就会用unsigned char的方法去解读了,所以 10011100 解读出来会是156。
上面就是第一种用法,指针的强制转换就是对于同一块地址的数据给它打上其他类型的数据标签后以那个类型的数据读出,再处理。
再举一个更加形象的栗子:
No.2
定义一个浮点数10.25,以及一个float类型和int类型的指针变量,我是64位操作系统,int占用32位,和float一样。对于float在计算机中的存储形式可以参考这篇文章浮点数的十进制和二进制转换,这边就不多赘述据。10.25,存储在计算机中是:0100 0001 0010 0100 0000 0000 0000 0000一共是32位,那么按照上面的思路,我把这块地址给他一个int的标签,那么上面这串数据用int读出是多少呢,答案就是1092878336。
另一种用法,大家一定发现了上面举的例子数据的长度都是一样的,8位,32位,那么如果数据长度不一样呢,这就是另一种形式了,请看例子:
No.3
我定义了一个char类型的,size是16的数组并打印出前面几个数据,p_a + 1即把指针指向下一个地址,因为数组的地址是连续的,所以指向下一个单元的数据,也就是数组的下一个数据被打印出来了,这个是没问题的,此时我把这个地址打上int的标签赋给一个int类型的指针,然后也对它进行加1打印的操作,显示的却是4个看似很乱的值,这可不是乱码,那么这四个值是怎么来的呢?可以把地址列一下:
我们结合int类型是占用了4个字节的知识,把前面四个字节给他当作一个变量,发现把第四个数据到第一个数据从高位到地位串起来,0 1 0 1(十进制)转换后就是 00000000 00000001 00000000 00000001,那么这个数据就是65537,那么第二个数131074呢,没错就是把第八个数据到第五个数据给他串起来,以此类推。
由上面的例子我们看出,指针+1是对于数据单元大小而言的,强转后数据的单元大小也就随之改变了,所以每次+1后地址跳转的也不一样。