【C上分之路】第二篇:数据的类型、表示、存储、类型转换,进制间的转换

数据类型

数据类型是程序的基础,是用来说明数据的类型,确定了数据的解释方式,让计算机和程序员不会产生歧义,决定了程序中数据和操作的意义。

数据类型分类

C语言中数据类型可以分为基本数据类型和复杂数据类型

  • 基本数据类型分为整数类型、浮点型、void类型(不对应具体的值,仅用于一些特殊的场合)
  • 派生数据类型分为枚举类型、数组类型、指针类型、结构体类型、联合体类型
  • C99标准添加_Bool类型,即逻辑值true和false。
  • C99标准添加_Complex类型,表示复数
  • C99标准添加_Imaginary类型,表示虚数

整数类型

C语言提供了3个附属关键字修饰基本整数类型:short、long、unsigned

类型存储大小值范围
char1 字节-128 到 127 或 0 到 255
unsigned char1 字节0 到 255
signed char1 字节-128 到 127
int2 或 4 字节-32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647
unsigned int2 或 4 字节0 到 65,535 或 0 到 4,294,967,295
short2 字节-32,768 到 32,767
unsigned short2 字节0 到 65,535
long4 字节-2,147,483,648 到 2,147,483,647
unsigned long4 字节0 到 4,294,967,295

*unsigned关键字修饰的整数类型只用于非负值的场合

char类型

char类型用于存储字符,从技术层面看,char是整数类型,char类型实际上存储的是整数而不是字符,计算机使用数字编码来处理字符,即用特定的整数表示特定的字符,即ASCII编码

标准ASCII码的范围是0~127,只需要7位二进制数即可表示

ASCII

浮点类型

C语言中浮点类型有float、double、long double

类型存储大小值范围精度
float4 字节1.2E-38 到 3.4E+386 位有效位
double8 字节2.3E-308 到 1.7E+30815 位有效位
long double16 字节3.4E-4932 到 1.1E+493219 位有效位

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

运行结果为:

sizeof结果

数据的表示

C语言中的整数默认就是十进制,还可以使用二进制、八进制和十六进制

为了将二进制、八进制、十六进制和十进制区分来表示,必须采用某种特殊的写法,即在数字前面加上特定的符号,也就是前缀

不同的进制数是为了方便表示数据,但是并不会影响数据被存储的方式

二进制

二进制由0跟1两个数字组成,使用是必须以0b或者0B,标准的C语言并不支持0b或0B开头的二进制写法,只有高版本的GCC和Visual Studio才支持二进制数字

二进制表示

八进制

八进制由0~7八个数字组成,逢八进一,使用时必须以数字0开头作为八进制整数的前缀

八进制表示

十六进制

十六进制由0-9,字母A-F(a~f)组成,使用时必须以0x或0X开头作为十六进制整数的前缀

十六进制表示

进制的转换说明

在C程序中,可以使用和显示不同进制的数,不同的进制要使用不同的转换说明

  • 以十进制显示数字时,使用%d;
  • 以八进制显示数字时,使用%o;
  • 以十六进制显示数字时,使用%x,要显示十六进制前缀时,使用%#x或%#X(x或X大小写区别在于显示时十六进制数是否为大小写)

进制转换

N进制转换成十进制

将二进制、八进制、十六进制向十六进制规则就是"按权相加",权即位权

N进制转换十进制的规则:

  1. 对于整数部分,从右往左看,第i位的位权等于N^i-1
  2. 对于小数部分,从左往右看,第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取余,逆序排列”

  1. 将N作为除数,用十进制数作为被除数除以N,得到一个商和余数
  2. 保留余数,将商继续除以N,又会得到一个新的商和余数
  3. 重复上述操作,直到商为0为止
  4. 逆序排序是指:余数从下往上组合为十进制转换成二进制的结果
十进制转二进制2

小数部分

十进制小数转换成N进制规则:“乘N取整,顺序排序”

  1. 用N乘以十进制小数,得到的积包含整数部分和小数部分
  2. 将积的整数部分取出,再用N乘以十进制小数,又得到一个新的积
  3. 重复上述操作,直到积中的小数部分为0,或者达到所要求的的精度为止
  4. 顺序排序是指:每一次取出得到积的整数部分从上往下组合为二进制结果
十进制转二进制小数部分

数字包含整数和小数部分,分别对整数部分和小数部分进行转换后再进行组合

二进制和八进制、十六进制的转换

二进制与八进制之间的转换

二进制整数转换为八进制整数时,每三位二进制数字转换为一位八进制数字,运算的顺序从低位往高位进行,高位不足三位用零补齐

二进制与八进制之间转换

二进制与十六进制之间的转换

二进制整数转换为十六进制整数时,每四位二进制数字转换为一位十六进制数字,运算的顺序是从低位向高位依次进行,高位不足四位用零补齐

二进制与十六进制间转换

数据在内存中的存储

前言

计算机要处理的数据信息都是以二进制形式存储在内存中。内存条是计算机中精密的部件,由电子元器件组成,元器件实际上就是电路;电路的电压会产生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

进制

补码计算

在计算机内存中,整数一致采用补码的形式存储,当读取整数时还要采用逆向的转换,以5+(-10)运算为例

补码运算

输出结果为:

x=5
y=-10
xy=-5

补码计算过程

补码运算图解

小数在内存中的存储

小数是与浮点数绑定在一起的,只有小数才使用浮点数格式来存储

浮点数是数字在内存中的一种存储格式,小数转化成浮点格式之后,小数点的位置发生了移动(浮动),浮点的位置由指数决定,所以这种表示小数的方式称为浮点数

C语言标准规定,小数在内存中以科学计算法形式来存储,存储形式为:

flt = (-1)^sign × mantissa × base^exponent
flt:为表示的小数
sign:为-1的指数,表示flt的正负号,取值只有01,值为0时表示正数,为1时表示负数
base:基数,即进制(2表示2进制,10表示十进制...)
mantissa:尾数或精度,并且1<=mantissa<base,即小数点前只能有一位数字
exponent:指数,是一个整数,可正可负
注意:计算机中科学计算法是可以基于任何进制的 
基于十进制: 7.3 x 10^2 = 730
基于二进制: 1.001 x 2^7 = 10010000

二进制形式浮点数的存储

C语言标准虽然没有明确规定浮点数以什么进制进行存储,但各种编译器都以二进制形式来存储浮点数,这样做贴近计算机硬件和减少转换次数

十进制转二进制,浮点数整数部分和小数部分分别转换之后然后再进行组合

浮点数十进制转二进制

浮点数的内存分布

C语言中常用的浮点数类型为float、double,float占四个字节,double占8个字节

浮点数的内存被分成了三部分,分别用来存储符号 sign、尾数 mantissa 和指数 exponent ,当浮点数的类型确定后,每一部分的位数就是固定的

浮点数内存分布
符号的存储

存储浮点数时,单独分配出一个位来用于符号的存储,用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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值