C语言中指针的理解4:指针与强制数据类型转换

C语言中指针的理解4:指针与强制数据类型转换

1.变量的数据类型的含义

首先来看这样一道2016年的408考试真题:

  • 有代码:short si=-32767; unsigned short usi=si;,则usi的值为?
  • 解析:short占4字节,16bit,si是有符号数,对应的二进制补码为1000 0000 0000 0001,而usi是无符号数,因此对于之前的补码,解析方式为直接将其当作原码解析即可,1000 0000 0000 0001为二进制原码时,对应的十进制数就是 2 15 + 2 0 = 32769 2^{15}+2^0=32769 215+20=32769

C语言中,所有类型的数据存储都是按照二进制格式存储在内存中的。所以计算机内存中存储的只有有0和1,如果只是单纯的给出一个二进制机器数,比如1000 0000 0000 0001,是看不出来是这个二进制机器数代表的真值的,因为它可能是int的,也可能是float的,或者还是其他类型,不同类型解析出来的真值是不一样的。

intcharshort等属于整形,它们的存储方式:真值转换成二进制补码存入内存的方式是相同的,只是每种类型可以占用的内存空间大小不同,所以这几种整形就彼此叫二进制兼容格式。而floatdouble的存储方式彼此不同,和整型更不同。

int a = 5;

对于上面的代码,编译器要做的是给a分配4字节空间,并且将5按照int类型的存储方式转成二进制补码存到a所对应的4字节内存空间中去,此时a做左值的。

printf("%d.\n",a);

当通过printf()去打印a的时候,a此时做右值,printf()内部的vprintf()函数会按照格式化字符串,就是printf()传参的第一个字符串参数中的%d之类的东西所代表的类型去解析a所对应的内存空间,解析出的值用来输出。

也就是说,存进去时是按照这个变量本身的数据类型来存储的,比如本例中aint所以按照int格式来存储),但是取出来时是按照printf()%d之类的格式化字符串的格式来提取的。此时虽然a所代表的内存空间中的二进制序列并没有变,内存是没被修改的。但是对这些二进制数据怎么理解,怎么把这些1010转成有意义的真值数字就不一定了。如果我们用%d来按照int格式解析则值自然还是5,但是如果用%f来解析,则printf()就以为a对应的内存空间中存储的是一个float类型的数,会按照float类型来解析,值自然是很奇怪的一个数字了。

总结:C语言中的数据类型的本质,就是决定了这个数在内存中怎么存储的问题,也就是决定了这个真值数如何转成存储到内存中的二进制机器数的问题。一定要记住的一点是内存只管存储1010的序列,而不管这些1010将来如何被解析。所以对于数据类型不能随便乱搞。

分析下面几个情况:

  • 按照int类型存却按照float类型取:一定会出错。
  • 按照int类型存却按照char类型取:有可能出错也有可能不出错。
  • 按照short类型存却按照int类型取:有可能出错也有可能不出错。
  • 按照float类型存却按照double取:一定会出错。

2.指针的数据类型的含义

指针的本质是变量,指针就是指针变量。但是一个指针涉及2个变量:指针变量自己本身和它指向的那个变量。int *p;定义指针变量时,p(指针变量本身)是int *类型,*p(指针指向的那个变量)是int类型的。

int *类型说白了就是指针类型,只要是指针类型在64位系统上就都是占8个字节,解析方式都是按照地址的方式来解析,里面存的64个二进制加起来表示一个内存地址。所以可以说:所有的指针类型,不管是int *,还是char *double *,对于它们在计算机内存中实际存储的二进制数据的解析方式是相同的,解析出来都是地址。但是对于指针所指向的那个变量来说,指针的类型就很重要了。指针所指向的那个变量的类型,它所对应的内存空间的解析方法都要取决于指针类型。比如指针是int *的,那么指针所指向的变量就是int类型的,对指针解引用时就要按照int的方法来解引用。

猜你喜欢

转载自blog.csdn.net/PecoHe/article/details/114265044