c语言中的基本数据类型有整数型(integer)和浮点型(float-point)两大类。所谓整数类型,就是没有小数部分的数啦,而浮点数差不多可以和数学中的实数对应。我们看上去这两种类型的区别在于能不能表示小数,但是在计算机中他们的表示方式是截然不同的。
位和字节
我们知道计算机中的数据都是以二进制的形式存储的。
位(bit)是计算机存储的基本单位,它可以容纳0或1中的一个。
字节(Byte)是常用的计算机存储单位,通常一个字节有8位,也就是有8位二进制数字。一个字节可以有2的8次方种0和1的不同组合。
我们平时说的K M G 等 都是用Byte为单位的。1 K = 1024 Byte 1M=1024K
int类型
int类型占多少个字节?能表示数的范围是多大?
实际上,答案并不固定,而是与机器系统有关。c标准规定了int类型的最小范围是-32767到32767,也就是最少有2字节(16位)。在我的机器上,int类型为4字节(32位)。可以使用sizeof操作符来查看你的机器上int类型的大小
原码、反码和补码
有符号整数在计算机里以补码的形式保存。这是由硬件决定而不是c语言决定的。之所以使用补码是因为它能简化运算规则。下面简要介绍一下原码 和 补码的转换。为了描述方便,假设int类型的字长为8位。
对于无符号数,不存在原码补码的概念。
十进制 ————> 二进制补码
1. 正数的补码是它的二进制原码
2.负数的补码是它的绝对值的二进制原码取反加一
例如: 7 的补码是 0000 0111
-7 的补码是 1111 1000 + 1 = 1111 1001
可以看出 7 + (-7) = 1 0000 0000 由于计算机的存储限制 最高位抛弃,结果为0000 0000
补码 ————> 十进制
1.最高位为0 是正数 直接转换该二进制数即可。
2.最高位为1 是负数 其绝对值等于该补码 取反加一 的二进制数
例如:0000 0111 为正数 等于 7
1111 1001 负数 绝对值等于 0000 0110 + 1 = 0000 0111 = 7(十进制) 结果为-7
int的范围
这里以2字节(16位)的int为例,16个1和0的组合共有2^16 = 65536种。
0000 0000 0000 0000表示0 。
0111 1111 1111 1111表示的是2^15 – 1 = 32767
1111 1111 1111 1111表示什么呢?我们按照上面的规则,这是一个负数 它的绝对值等于0000 0000 0000 0001 因此表示-1
1000 0000 0000 0000表示什么呢? 表示负的 0111 1111 1111 1111 + 1 = 1000 0000 0000 0000 = 2^15 = 32768 因此表示-32768
所以 16位的int类型的范围是-32768 到+32767
其他整数类型
c语言提供四个修饰int的关键字: short long signed unsigned
c标准规定short类型的大小不超过int long类型的大小不小于int 但是它们具体是多大 因机器而异。一般来说 long long为64位 long为32位 short为16位 int为16或32位。
在我的机器上
整数溢出
如果整数太大超出了范围会怎样呢?我们知道了整数在内存中的表示形式后,这个问题就迎刃而解了!
上面的例子中,n = 32767 它在内存中为 0111 1111 1111 1111
执行n+1后 等于 1000 0000 0000 0000 结果就是-32768啦
再加一 补码为 1000 0000 0000 0001 是负的0111 1111 1111 1110 + 1 = 0111 1111 1111 1111 = 32767
printf的格式说明符
使用库函数printf的时候我们要注意要输出什么类型的数据 就要用什么类型的说明符。因为计算机中的数据是二进制形式,因此一样的数据 如果是不同的类型,他表示的东西也是不一样的
1111 1001如果表示有符号整数,那么就是表示-7
如果表示的是无符号整数 那么表示的是249
因此,如果printf的类型说明符和实际的参数类型不一致 就可能产生错误的结果。
unsigned int自动转换带来的问题
无符号类型在计算时可能由于类型转换带来错误。
由于b是int类型,该例子中int类型不能表示所有的unsigned int 因此 a > b表达式中 b被转化为unsigned int类型 产生错误的结果。
因此,要谨慎使用无符号整数类型。不要因为一些计数没有负数就是用无符号,依然可以使用int以避免复杂的麻烦。
char类型
char类型用于存储字母、数字和标点符号等字符,但是问题是计算机只认识二进制,所以计算机用一种数字编码来表示字符。因此char类型在技术实现上是整数类型。
最常用的编码是ASCII码,标准ASCII的码值得范围是0到127 只需7位就可以表示。
char类型通常定义为使用8为内存单元。在一些编译器中char作为有符号数,而有些编译器中char是无符号数,可以通过编译器手册来确定。c还允许使用signed和unsigned来表示char的符号属性。
浮点数类型
c标准规定,float类型至少表示6位有效数字,取值范围10^-37到10^37 。
double类型至少表示10位有效数字。
由于计算机中的数据是离散的 不可能表示所有连续的整数。浮点数的存储也有一定的误差。
例如把一个数+1然后-1 这个数并不一定和原来的数相等。
这是因为计算机缺少足够的精度来进行计算。