前言——数据类型
在介绍数据类型转换之前,我们首先要清楚一个知识点:数据类型的级别高低。
我们所提到的数据类型,比如整数型int,浮点型float,它们在计算机中其实是以二进制–也就是0和1的方式存储在计算机的内存中。
在计算机中,一个字节是8个bite,也就是8个0和1组成的。这样我们就可以通过不同的0和1的组合来储存不同的数据。例如,我们要存储整形7–在计算机内是00000000 00000000 00000000 00000111来进行的储存。
那么怎样存储这么多不同的数据内型呢?
如果我们对于所有的数据类型都使用相同字节,有些数据类型不需要那么大的空间就可以进行存储,这就会造成浪费空间;而有些需要多个字节才能描述的数据类型,那么会使得空间不够,会造成数据失真。所有,我们对于不同的数据类型开辟不同的内存空间,该内存空间的大小能够存储完全描述具体数据类型的信息。
具体的有关数据类型是怎样通过0和1来表达的可以看一下的链接:
int类型在计算机中的存储
浮点数(float和double)在计算机底层的存储机制
(这是我认为两篇可以很好理解的博客)
(将整形和浮点型理解后,其他的数据类型都可以很好的理解其底层存储原理)
自动类型转换
在大致的了解了数据类型在底层上是如何储存之后,我们可以根据开辟储存空间的大小,将数据类型分为不同的级别:long double , double , flaot , unsigned long long , long long , unsigned long , long , unsigned int , int , unsigned short , short , unsigned char , char
(其中unsigned 表示是无符号的数据类型,在开辟的空间大小上,其实是一样大的)
对于unsigned和signed的区别可以看一下下面的这篇博客,能够稍稍理解一二:
unsigned和signed(默认)的区别
当使用不同的字节空间来存储数据类型之后,如果我们将两个不同的数据类型来进行表达式运算会怎么样?
其实在计算机内,只能够以相同的数据类型来进行运算,那么在进行表达式运算的时候,就会把两种不同数据类型的数据转会为较高级别的数据类型。这时候,计算机就会进行自动的类型转换。
-
如果在表达式中涉及到类型转换时,unsigned char,char,unsigned short和short都会转换为int,如果有必要则会被转换成unsigned int。
原因如下:
(因为short,int,long其实都是整数类型,只是开辟存储空间的大小不同,c语言中只规定了short占用的存储空间不多于int,long占用的存储空间不小于int——也就是short<=int<=long。那么当short=int时——指的是存储空间的大小——就会有unsigned short比int大,这种情况下unsigned short就不在转换为int了,而是转换为unsigned int类型) -
涉及两种数据类型的运算的时候,两个值会被转换为两者间的更高级的那一者。
(比如3 + 2.00——‘3’是int类型的变量,‘2.00’是double类型——在编译器中,浮点型常量默认为是double类型的——那么这个表达式中,明显‘2.00’的级别更高,所以‘3’会被转换为‘3.00’的double类型,这个表达式的结果就是‘5.00’) -
在赋值表达式中,计算的结果会被转换为被赋值变量的数据类型——这个过程不是数据类型向高级别转换,它取决于被赋值变量的数据类型,被赋值变量的数据类型是啥,就转换为啥数据类型。
在赋值表达式中,计算的结果会被转换为被赋值变量的数据类型——这个过程不是数据类型向高级别转换,它取决于被赋值变量的数据类型,被赋值变量的数据类型是啥,就转换为啥数据类型。
(由较小类型转换到较大的类型,这种转化被称为升级(promotion),而把一种数据类型转换成更低级别的类型,这中转换被称为降级(demotion)。)
例如:我开辟一个整型变量a,来进行上述表达式的运算,我们已经知道右边的表达式的结果为‘5.00。
现在左边为int类型的变量,右边为double类型的value值,进行赋值运算,所以应该将‘5.00’转换为‘5’赋值到a中。
#include<stdio.h>
int main()
{
int a;
a = 2 + 3.00;
return 0;
}
通过打断点进行监视,我们发现确实和分析的是相同的
- 当作为函数参数传递的时候,char和short被转换成int,float被转换成double。(在此不做详细介绍)
类型的升级通常是不会有什么问题的,但是类型的降级却会导致真正的麻烦。原因也很简单:较低类型可能放不下整个数字。例如,一个8位的char类型变量,最大能存储的是0~255,现在存储整数101没有什么问题,但是如果是整数22553,则存储不小。
- 如果把一个浮点值转换成整数类型会怎样呢?
当浮点类型被降级位整数类型的时候,原来的浮点值会被截断。例如23.12和23.99会被截断为23。
#include<stdio.h>
int main()
{
int a;
a = 23.99;
return 0;
}
- 如果是int类型转换为char型是怎样的呢?
大部分的系统中int是32位的,char是8位的,当int转换为char时,是去int的最后一个字节,也就是最后一个8位的。例如将1107转换为char型
在这里我们可以看到整数1107的二进制数为
00000000 00000000 00000100 01010011
所以它的后八位是01010011,转换为整数就是83
#include<stdio.h>
int main()
{
char a;
a = 1107;
printf("%c", a);
return 0;
}
至于这里打印的是S,而不是83,是因为这是char型的数据类型,在ASCII码中83对应的就是S。
(可以去看一下ASCII码和char的具体讲解)
强制类型转换
- 对于强制类型转换,c语言提供了强制类型转换运算符(cast operator)
其通用的形式为:
(type)
举个例子:
int mice1,mice2;
mice1 = 1.6+1.7;
mice2 = (int)1.6 + (int)1.7;
我们根据前面讲的,1.6 + 1.7都是double型,所以可以不用类型转换而进行运算,得到的值为3.1。这个时候,进行赋值运算,将3.1转换成整形int,将小数部分截断。所以得到mice1 = 3。
而在第二个表达式中,我们使用了强制转换运算符,在还没进行加法运算的时候,将1.7和1.6转换成了int类型。1.6转换为int型,将小数部分截断,变为1;同理,1.7转换为int类型也变成了1。然后在进行加法运算1+1=2,所以可以得到mice2=2。
我们可以看到与分析的一样mice1 =3,mice2 =2。
(当我们需要进行精确的类型转换的时候,或者在程序中表明类型转换的意图,这时,就需要用到强制类型转换。)