文章目录
数据类型
数据类型是程序的基础,是用来说明数据的类型,确定了数据的解释方式,让计算机和程序员不会产生歧义,决定了程序中数据和操作的意义。
数据类型分类
C语言中数据类型可以分为基本数据类型和复杂数据类型
- 基本数据类型分为整数类型、浮点型、void类型(不对应具体的值,仅用于一些特殊的场合)
- 派生数据类型分为枚举类型、数组类型、指针类型、结构体类型、联合体类型
- C99标准添加_Bool类型,即逻辑值true和false。
- C99标准添加_Complex类型,表示复数
- C99标准添加_Imaginary类型,表示虚数
整数类型
C语言提供了3个附属关键字修饰基本整数类型:short、long、unsigned
类型 | 存储大小 | 值范围 |
---|---|---|
char | 1 字节 | -128 到 127 或 0 到 255 |
unsigned char | 1 字节 | 0 到 255 |
signed char | 1 字节 | -128 到 127 |
int | 2 或 4 字节 | -32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647 |
unsigned int | 2 或 4 字节 | 0 到 65,535 或 0 到 4,294,967,295 |
short | 2 字节 | -32,768 到 32,767 |
unsigned short | 2 字节 | 0 到 65,535 |
long | 4 字节 | -2,147,483,648 到 2,147,483,647 |
unsigned long | 4 字节 | 0 到 4,294,967,295 |
*unsigned关键字修饰的整数类型只用于非负值的场合
char类型
char类型用于存储字符,从技术层面看,char是整数类型,char类型实际上存储的是整数而不是字符,计算机使用数字编码来处理字符,即用特定的整数表示特定的字符,即ASCII编码
标准ASCII码的范围是0~127,只需要7位二进制数即可表示
![ASCII](https://cdn.jsdelivr.net/gh/babybeekeeper/pic_Hosting@master/20211026/ASCII.fmqkas5axeg.jpg)
浮点类型
C语言中浮点类型有float、double、long double
类型 | 存储大小 | 值范围 | 精度 |
---|---|---|---|
float | 4 字节 | 1.2E-38 到 3.4E+38 | 6 位有效位 |
double | 8 字节 | 2.3E-308 到 1.7E+308 | 15 位有效位 |
long double | 16 字节 | 3.4E-4932 到 1.1E+4932 | 19 位有效位 |
C标准规定,float类型,表示单精度,必须至少能表示6位有效数字,且取值范围至少是10^-37 ~10^37。系统存储一个浮点数要占用32位,其中8位用于表示指数的值和符号,剩下24位用于表示非指数部分(也叫作尾数或有效数)及其符号
C语言提供的另一种浮点类型是double(意为双精度)。double类型个float类型的最小取值范围相同,但至少必须能表示10位有效数字。double占用64位而不是32位,相比于float类型,多出的32位全部用来表示非指数部分,这样增加了有效数字的位数,即提供了精度,还纳入了舍入误差
复数和虚数类型
许多科学和工程计算都要用到复数和虚数,C99标准支持复数类型和虚数类型,C语言有3种复数类型和3种虚数类型
-
复数类型:float _Complex、double _Complex、long double _Complex
-
虚数类型:floa _Imaginary、double _Imaginary、long double _Imaginary
类型大小
sizeof是C语言的内置运算符,以字节为单位给出指定类型的大小,C99和C11提供%zd转换说明匹配sizeof的返回类型
![sizeof](https://cdn.jsdelivr.net/gh/babybeekeeper/pic_Hosting@master/20211028/sizeof.4s0t7akgd060.png)
运行结果为:
![sizeof结果](https://cdn.jsdelivr.net/gh/babybeekeeper/pic_Hosting@master/20211028/sizeof结果.3hgnpc60q460.png)
数据的表示
C语言中的整数默认就是十进制,还可以使用二进制、八进制和十六进制
为了将二进制、八进制、十六进制和十进制区分来表示,必须采用某种特殊的写法,即在数字前面加上特定的符号,也就是前缀
不同的进制数是为了方便表示数据,但是并不会影响数据被存储的方式
二进制
二进制由0跟1两个数字组成,使用是必须以0b或者0B,标准的C语言并不支持0b或0B开头的二进制写法,只有高版本的GCC和Visual Studio才支持二进制数字
![二进制表示](https://cdn.jsdelivr.net/gh/babybeekeeper/pic_Hosting@master/20211028/二进制表示.4quv5pl2bmg0.png)
八进制
八进制由0~7八个数字组成,逢八进一,使用时必须以数字0开头作为八进制整数的前缀
![八进制表示](https://cdn.jsdelivr.net/gh/babybeekeeper/pic_Hosting@master/20211028/八进制表示.5hdrp6jcxig0.png)
十六进制
十六进制由0-9,字母A-F(a~f)组成,使用时必须以0x或0X开头作为十六进制整数的前缀
![十六进制表示](https://cdn.jsdelivr.net/gh/babybeekeeper/pic_Hosting@master/20211028/十六进制表示.5a5byga7p3k0.png)
进制的转换说明
在C程序中,可以使用和显示不同进制的数,不同的进制要使用不同的转换说明
- 以十进制显示数字时,使用%d;
- 以八进制显示数字时,使用%o;
- 以十六进制显示数字时,使用%x,要显示十六进制前缀时,使用%#x或%#X(x或X大小写区别在于显示时十六进制数是否为大小写)
进制转换
N进制转换成十进制
将二进制、八进制、十六进制向十六进制规则就是"按权相加",权即位权
N进制转换十进制的规则:
- 对于整数部分,从右往左看,第i位的位权等于N^i-1
- 对于小数部分,从左往右看,第j位的位权等于N^-j
整数部分
二进制数字转换成十进制
10101 = 1x2^4 + 0x2^3 + 1x2^2 + 0x2^1 + 1x2^0 = 21(十进制)
八进制数字转换成十进制
53627 = 5×8^4 + 3×8^3 + 6×8^2 + 2×8^1 + 7×8^0 = 22423(十进制)
十六进制转换成十进制
9FA8C = 9×16^4 + 15×16^3 + 10×16^2 + 8×16^1 + 12×16^0 = 653964(十进制)
小数部分
二进制数字转换成十进制
1010.1101 = 1×2^3 + 0×2^2 + 1×2^1 + 0×2^0 + 1×2^-1 + 1×2^-2 + 0×2^-3 + 1×2^-4 = 10.8125(十进制)
八进制数字转换成十进制
423.5176 = 4×8^2 + 2×8^1 + 3×8^0 + 5×8^-1 + 1×8^-2 + 7×8^-3 + 6×8^-4 = 275.65576171875(十进制)
十进制转换N进制
整数部分
十进制整数转换成N进制规则:“除N取余,逆序排列”
- 将N作为除数,用十进制数作为被除数除以N,得到一个商和余数
- 保留余数,将商继续除以N,又会得到一个新的商和余数
- 重复上述操作,直到商为0为止
- 逆序排序是指:余数从下往上组合为十进制转换成二进制的结果
![十进制转二进制2](https://cdn.jsdelivr.net/gh/babybeekeeper/pic_Hosting@master/20211028/十进制转二进制2.7dw6zrxhq5g0.png)
小数部分
十进制小数转换成N进制规则:“乘N取整,顺序排序”
- 用N乘以十进制小数,得到的积包含整数部分和小数部分
- 将积的整数部分取出,再用N乘以十进制小数,又得到一个新的积
- 重复上述操作,直到积中的小数部分为0,或者达到所要求的的精度为止
- 顺序排序是指:每一次取出得到积的整数部分从上往下组合为二进制结果
![十进制转二进制小数部分](https://cdn.jsdelivr.net/gh/babybeekeeper/pic_Hosting@master/20211028/十进制转二进制小数部分.6l3d9bqsqqs0.png)
数字包含整数和小数部分,分别对整数部分和小数部分进行转换后再进行组合
二进制和八进制、十六进制的转换
二进制与八进制之间的转换
二进制整数转换为八进制整数时,每三位二进制数字转换为一位八进制数字,运算的顺序从低位往高位进行,高位不足三位用零补齐
![二进制与八进制之间转换](https://cdn.jsdelivr.net/gh/babybeekeeper/pic_Hosting@master/20211028/二进制与八进制之间转换.39sgt42782i0.png)
二进制与十六进制之间的转换
二进制整数转换为十六进制整数时,每四位二进制数字转换为一位十六进制数字,运算的顺序是从低位向高位依次进行,高位不足四位用零补齐
![二进制与十六进制间转换](https://cdn.jsdelivr.net/gh/babybeekeeper/pic_Hosting@master/20211028/二进制与十六进制间转换.3ocscwckyyq0.png)
数据在内存中的存储
前言
计算机要处理的数据信息都是以二进制形式存储在内存中。内存条是计算机中精密的部件,由电子元器件组成,元器件实际上就是电路;电路的电压会产生0V和5V两种电压;5V是表示通电,用1来表示,0V是断电,用0来表示,即元器件的状态有0和1两种
1个元器件称为1比特(Bit)或1位,是最小的存储单元,可以存储0或1
8个元器件称为1字节(Byte),最常用的存储单位,可以存储2^8种0、1的组合
字(word)由一个字节或者多个字节构成,是设计计算机时给定的自然存储单位,决定了CPU一次操作处理实际位数的多少,计算机的字长越大,其转移数据越快,允许的内存访问也更多
整数在内存中的存储
原码
将一个整数转换成二进制形式,就是原码。即原码就是一个整数本来的二进制形式
反码
正数的反码同原码一样;负数的反码是将原码中除符号位以外的所有位(数值位)取反,0与1互换
补码
正数的补码与反码、原码一样;负数的的补码是其反码加1
![进制](https://cdn.jsdelivr.net/gh/babybeekeeper/pic_Hosting@master/20211028/进制.22x1kk64qark.png)
补码计算
在计算机内存中,整数一致采用补码的形式存储,当读取整数时还要采用逆向的转换,以5+(-10)运算为例
![补码运算](https://cdn.jsdelivr.net/gh/babybeekeeper/pic_Hosting@master/20211028/补码运算.61pukp0e7nk0.png)
输出结果为:
x=5
y=-10
xy=-5
补码计算过程
![补码运算图解](https://cdn.jsdelivr.net/gh/babybeekeeper/pic_Hosting@master/20211028/补码运算图解.514w5n94yn40.png)
小数在内存中的存储
小数是与浮点数绑定在一起的,只有小数才使用浮点数格式来存储
浮点数是数字在内存中的一种存储格式,小数转化成浮点格式之后,小数点的位置发生了移动(浮动),浮点的位置由指数决定,所以这种表示小数的方式称为浮点数
C语言标准规定,小数在内存中以科学计算法形式来存储,存储形式为:
flt = (-1)^sign × mantissa × base^exponent
flt:为表示的小数
sign:为-1的指数,表示flt的正负号,取值只有0跟1,值为0时表示正数,为1时表示负数
base:基数,即进制(2表示2进制,10表示十进制...)
mantissa:尾数或精度,并且1<=mantissa<base,即小数点前只能有一位数字
exponent:指数,是一个整数,可正可负
注意:计算机中科学计算法是可以基于任何进制的
基于十进制: 7.3 x 10^2 = 730
基于二进制: 1.001 x 2^7 = 10010000
二进制形式浮点数的存储
C语言标准虽然没有明确规定浮点数以什么进制进行存储,但各种编译器都以二进制形式来存储浮点数,这样做贴近计算机硬件和减少转换次数
十进制转二进制,浮点数整数部分和小数部分分别转换之后然后再进行组合
![浮点数十进制转二进制](https://cdn.jsdelivr.net/gh/babybeekeeper/pic_Hosting@master/20211029/浮点数十进制转二进制.6x5w1dwqts40.png)
浮点数的内存分布
C语言中常用的浮点数类型为float、double,float占四个字节,double占8个字节
浮点数的内存被分成了三部分,分别用来存储符号 sign、尾数 mantissa 和指数 exponent ,当浮点数的类型确定后,每一部分的位数就是固定的
![浮点数内存分布](https://cdn.jsdelivr.net/gh/babybeekeeper/pic_Hosting@master/20211029/浮点数内存分布.60tctlz7qp80.png)
符号的存储
存储浮点数时,单独分配出一个位来用于符号的存储,用0表示正数,用1表示负数
尾数的存储
当采用二进制形式时,尾数部分的取值范围为1<=mantissa<2,即尾数的整数部分一定是1,是一个恒定的值,无需在内存中提现出来,只要把小数点后面的二进制数字放入到内存中即可
如果采用其他base进制存储浮点数,那尾数的整数部分范围不确定,是在1~base之间任何一个值,这样一来尾数的整数部分就不能省略了,必须在内存中体现出来,二进制则可以节省一个位的内存
指数的存储
指数是一个整数,并且有正负之分,所以不仅要存储它的值,还得能区分出正负号来
假设指数部分占内存的n位,先确定指数部分的取值范围为0~2^n,然后再得到这个取值范围的中间值mid = 2^(n-1) - 1,写入指数时加上这个中间值,读取指数时减去这个中间值,这样符号和值都能确定下来
浮点数的精度
对于float类型来说,二进制存储时尾数部分占23位,外加一个隐含的整数1,一共24位。最后一位可能是精确数字也有可能是近似数字,能保证精确数字的是23位,最多有24位有效数字,整体的精度为23-24,2^24转换成十进制16777216,一共8位,即得出十进制形式的精度为7~8
同理double,二进制形式的精度为52~53
数据类型转换
数据类型转换是将数据(变量、数值、表达式的结果)从一种类型转换为另一种类型,数据类型转换主要可以分为隐式类型转换和显示类型转换
隐式类型转换
隐式类型转换,即自动类型转换,就是编译器隐式地进行的数据类型转换,是编译器在编译阶段进行类型检查时发生
隐式类型转换规则
- 在条件语句中,非布尔值转换成布尔值
- 初始化过程中,初始值转换为变量类型,赋值时右侧运算对象类型转换为左侧运算对象类型
- 算术运算或关系运算对象有多种类型,需要转换成同一类型
- 函数调用时会发生类型转换
- 在表达式中,比int类型小的整数值提升为较大的整数类型
- 所有的浮点运算都是以双精度进行,运算中只有float也要转换为double类型
- 转换按照数据长度增加的方向进行,以保证数值不失真,即精度不降低
显示类型转换
显示类型转换,即强制类型转换,需要程序员通过特定格式的代码来明确指明的一种类型转换
强制类型转换格式:
(typename) expr
typename:转换类型名
expr:表达式
类型转换的临时性
无论是强制类型转换还是隐式类型转换,只是为了当下运算做的临时类型转换,类型转换的结果只会保存在临时的内存空间,不会改变数据原来的类型和值
输出结果为:
x=5.600000 y=5 z=5
总结
数据类型是整个程序的基础,学习了各个数据类型和大小,数据的表示方式为二进制、八进制、十进制、十六进制,进制间的转换规则,数据在内存中的存储方式,以及类型转换的原则
赶紧学习起来吧!我是一个正在努力找回自我的人,希望能和一起学习的人成长,有错误的地方请各位大佬帮忙指正,如果看完觉得对你们有帮助就记得给我点赞哦! peace&love