C语言中的不同类型的取值范围
前言
C语言中,我们知道最基本的数据类型有int整型,float和double浮点型,char字符型,在计算机里,他们的取值并不是任意和无限的,都有相应的取值范围,那么计算机是如何存储和计算的呢,接下来为大家分析和讲解。
一、进制知识
首先我们来了解下进制,我们平时说的数字和计算都是按照十进制来进行的,从0 ~ 9,逢10就进1,称为十进制。计算机中存储的数据都是二进制,从0 ~ 1,逢2就进1,还有类似的八进制,而十六进制则是0 1 2 3 4 5 6 7 8 9 A B C D E F 这16个数组成。
int num = 0b101101;//前面加0b表示二进制
printf("十进制 %d\n",num);
printf("八进制 %o\n",num);
printf("十六进制 %x\n",num);
打印结果:
十进制是 45
八进制是 55
十六进制是 2d
二、计算机的内存知识
计算机的只能存储和识别二进制数,内存相当于由很多个格子组成,每个格子里存储的是0或1,每个格子我们叫做一个二进制位,英文用bit表示,8个二进制位分为一组,叫做一个字节,英文用byte表示,数量关系如下:
8 bit = 1 byte,
1024 byte = 1 KB,
1024 KB = 1 MB,
1024 MB = 1 GB,
1024 GB = 1 TB
数据在内存的存储方式:
1 | 0 | 1 | 0 | 1 | 1 | 0 | 1 |
---|---|---|---|---|---|---|---|
0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 |
三、 原码,反码,补码
一个整型数据,如果不考虑正负,一个十进制数的原码就是它的二进制形式,如果有正负,最高位(左边数起第一位)作为符号位,0表示正数,1表示负数,剩下的位数,就是这个数绝对值的二进制形式。C语言中的数据默认是有正负的。
正数的反码就是其原码,负数的反码是符号位不变,其他位取反。正数的补码就是其原码,负数的补码是反码+1。
一个十进制数11,假设用一个字节存储,原码,反码,补码表示如下:
原码 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 |
---|---|---|---|---|---|---|---|---|
反码 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 |
补码 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 1 |
一个十进制数-13,假设用一个字节存储,原码,反码,补码表示如下:
原码 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 1 |
---|---|---|---|---|---|---|---|---|
反码 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 |
补码 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 |
C语言中,任何数据都是以补码的形式存储在内存当中,为什么呢,计算机中只有加法没有减法,用补码做运算效率是最高的,我们举个简单的例子,5的原码是0000 0101,-5的原码是1000 0101,补码是 1111 1011,如果要计算加法 5 + -5 ,原码相加结果为 1000 1010 ,转换为十进制等于-10,如果补码相加,结果为 0000 0000,转换为十进制等于0,所以计算机中的数据都是以补码的形式储存。
四、 数据的取值范围
一般的,C语言中,int类型数据占4个字节,float类型占4个字节,double类型占8个字节,char类型占1个字节,不同的编译器给变量分配的字节数不同,可以使用sizeof(类型)函数来获得类型占据的字节数。
接下来以char类型为例,讲解它的取值范围,char占据1个字节8个二进制位,当无符号时,最小为0,最大的数值是 1111 1111,转换为十进制是28-1=255,当有符号时,最高位表示符号,最大是0111 1111,转换为十进制是27-1=127,注意,这时我们会推理,最小值应该是1111 1111,十进制是-127,然而并不是,有符号字符型char的最小值是-128,在内存中以补码1000 0000的形式储存,-128这个数它没有原码,也没有反码,只有补码,如果按照原码转补码的计算方法逆推-128的原码,1000 0000 减 1 后-128的符号位就会由1变为0,不再是负数,所以-128只有补码 1000 0000,没有原码和反码,-127的原码是 1111 1111,补码是 1000 0001,-128的补码由-127的补码减1得到。综上,有符号字符型char的取值范围是是 -128~127 即 -27~(27-1)。
按照以上的推理方法,我们可以推断出int类型的取值范围。至于浮点型float和double的储存会比较复杂,float类型占4个字节,在存储时,系统将实型数据分成小数部分和指数部分两个部分,分别存放,小数部分小数点前面的数为0。以3.14159为例:+ 0.313159 x 101
数符 | 小数部分 | 指数 |
---|---|---|
+ | . 3 1 4 1 5 9 | 1 |
实际上在计算机中是用二进制数来表示小数部分以及用2的幂次来表示指数部分,在4个字节中,究竟用多少位来表示小数部分,多少位来表示指数部分,不同的编译器并不相同,有的编译系统以24位表示小数部分(包括符号),以8位表示指数部分。
由于二进制形式表示一个实数以及存储单元的长度是有限的,因此不可能得到完全精确的值,只能存储成有限的精度,float类型的有效数字是6位,数值范围是 -3.4x1038~ 3.4x1038。
C语言中基本类型的取值范围
类型 | 字节数 | 取值范围 |
---|---|---|
int(有符号) | 4 | -231 ~ (231-1) |
int(无符号) | 4 | 0 ~ (232-1) |
char(有符号) | 1 | -27 ~ (27-1) |
char(无符号) | 1 | 0 ~ (28-1) |
float | 4 | 0以及1.2x10-38~3.4x1038(绝对值) |
double | 8 | 0以及2.3x10-308~1.7x10308(绝对值) |