为什么是0.1呢
前言
随着不断的学习(mo yu),越来越意识到c/c++的重要性。虽然以前在课堂上学过,但总觉得之前学的只是整个c语言大海里的一个微小的水分子。所以有了重新开始学习的想法,可能时间有点晚了,但越是这样越要加油呀。
这个系列目前主要用来记录一些我觉得重要,需要多看几次的知识点,也许中间会插入一些练习题。(哈哈其实是印象笔记只支持绑定两个设备,所以想到用博客来记录笔记了emm)
c语言基础数据类型笔记
输出不同的进制
在C程序中,既可以使用和显示不同进制的数。不同的进制要使用不同 的转换说明。以十进制显示数字,使用%d;以八进制显示数字,使用%o; 以十六进制显示数字,使用%x。另外,要显示各进制数的前缀0、0x和0X, 必须分别使用%#o、%#x、%#X
十六进制与二进制的转换
十六进制数的每一位的数恰好由4位二进制数表示。例如,十六进制数3是0011,十六 进制数5是0101。因此,十六进制数35的位组合(bit pattern)是00110101, 十六进制数53的位组合是01010011。
c语言的int范围
一般而言,储存一个int要占用一个 机器字长。因此,早期的16位IBM PC兼容机使用16位来储存一个int值,其 取值范围(即int值的取值范围)是-32768~32767。目前的个人计算机一般 是32位,因此用32位储存一个int值。现在,个人计算机产业正逐步向着64位 处理器发展,自然能储存更大的整数。ISO C规定int的取值范围最小 为-32768~32767,即2的16次方种可能。
c语言其他数据类型
short int类型(或者简写为short)占用的存储空间可能比int类型少,常用于较小数值的场合以节省空间。
与int类似,short是有符号类型。
long int或long占用的存储空间可能比int多,适用于较大数值的场合。与int类似,long是有符号类型。
long long int或long long(C99标准加入)占用的储存空间可能比long多,适用于更大数值的场合。该类型至少占64位。与int类似,long long是有符号 类型。
unsigned int或unsigned只用于非负值的场合。这种类型与有符号类型表 示的范围不同。例如,16位unsigned int允许的取值范围是0~65535,而不是-32768~32767。用于表示正负号的位现在用于表示另一个二进制位,所 以无符号整型可以表示更大的数。
在C90标准中,添加了unsigned long int或unsigned long和unsigned int或 unsigned short类型。C99标准又添加了unsigned long long int或unsigned long long。
在任何有符号类型前面添加关键字signed,可强调使用有符号类型的意 图。例如,short、short int、signed short、signed short int都表示同一种类型。
现在,个人计算机上最常见的设置是,long long占64位,long占32位, short占16位,int占16位或32位(依计算机的自然字长而定)。原则上,这4 种类型代表4种不同的大小,但是在实际使用中,有些类型之间通常有重叠。
类型的选择
首先,考虑unsigned类型。这种类型的数常用于计数,因为计数不用负数。而且,unsigned类型可以表示更大的正数。
如果一个数超出了int类型的取值范围,且在long类型的取值范围内时, 使用long类型。然而,对于那些long占用的空间比int大的系统,使用long类 型会减慢运算速度。因此,如非必要,请不要使用long类型。另外要注意一 点:如果在long类型和int类型占用空间相同的机器上编写代码,当确实需要 32位的整数时,应使用long类型而不是int类型,以便把程序移植到16位机后 仍然可以正常工作。类似地,如果确实需要64位的整数,应使用long long类型。
如果在int设置为32位的系统中要使用16位的值,应使用short类型以节省 存储空间。通常,只有当程序使用相对于系统可用内存较大的整型数组时,才需要重点考虑节省空间的问题。使用short类型的另一个原因是,计算机中 某些组件使用的硬件寄存器是16位。
八进制和十六进制常量被视为int类型。如果值太大,编译器会尝试使用 unsigned int。如果还不够大,编译器会依次使用long、unsigned long、long long和unsigned long long类型。
整数溢出
可以把无符号整数j看作是汽车的里程表。当达到它能表示的最大值 时,会重新从起始点开始。整数 i 也是类似的情况。它们主要的区别是,在 超过最大值时,unsigned int 类型的变量 j 从 0开始;而int类型的变量i则从 −2147483648开始
打印short、long、long long和unsigned类型
打印unsigned int类型的值,使用%u转换说明;打印long类型的值,使用%ld转换说明。如果系统中int和long的大小相同,使用%d就行。但是,这样的程序被移植到其他系统(int和long类型的大小不同)中会无法正常工作。在x和o前面可以使用l前缀,%lx表示以十六进制格式打印long类型整数,%lo表示以八进制格式打印long类型整数。注意,虽然C允许使用大写或小写的常量后缀,但是在转换说明中只能用小写。
C语言有多种printf()格式。对于short类型,可以使用h前缀。%hd表示以十进制显示short类型的整数,%ho表示以八进制显示short类型的整数。h和l前缀都可以和u一起使用,用于表示无符号类型。例如,%lu表示打印 unsigned long类型的值。对于支持long long类型的系统,%lld和%llu分别表示有符号和无符号类型。
数值转换
给函数传递参数时,C编译器把short类型的值自动转换成int类型的值。你可能会提出疑问:为什么要进行转换?h修饰符有什么用?第1个问题的答案是, int类型被认为是计算机处理整数类型时最高效的类型。因此,在short和int类型的大小不同的计算机中,用int类型的参数传递速度更快。第2个问题的答案是,使用h修饰符可以显示较大整数被截断成 short 类型值的情况。把 65537 以二进制格式写成一个 32 位数是 00000000000000010000000000000001。使用%hd,printf()只会查看后 16 位,所以显示的值是 1。
打印浮点值
printf()函数使用%f转换说明打印十进制记数法的float和double类型浮点数,用%e打印指数记数法的浮点数。如果系统支持十六进制格式的浮点数,可用a和A分别代替e和E。打印long double类型要使用%Lf、%Le或%La 转换说明。给那些未在函数原型中显式说明参数类型的函数(如,printf())传递参数时,C编译器会把float类型的值自动转换成double类型。
浮点值的上溢和下溢
上溢:当计算导致数字过 大,超过当前类型能表达的范围时,就会发生上溢。在这种情况下会赋一个表示无穷大的特定值,而且printf()显示该值为inf或infinity(或者具有无穷含义的其他内容)。
下溢:当有一个数字是float类型能用全部精度表示的最小数字。现在把它除以2。通常,这个操作会减小指数部分,但是假设的情况中,指数已经是最小值了。所以计算机只好把尾数部分的位向右移,空出第 1 个二进制位,并丢弃最后一个二进制数。以十进制为例,把一个有4位有效数字的数(如,0.1234E-10)除以10,得到的结果是0.0123E-10。虽然得到了结果,但是在计算过程中却损失了原末尾有效位上的数字。这种情况叫作下溢(underflow)。C语言把损失了类型全精度的浮点值称为低于正常的 (subnormal)浮点值。因此,把最小的正浮点数除以 2将得到一个低于正常 的值。如果除以一个非常大的值,会导致所有的位都为0(损失了大部分)。
还有另一个特殊的浮点值NaN(not a number的缩写)。
浮点数舍入错误
给定一个数,加上1,再减去原来给定的数,结果是多少?你一定认为是1。但是,实际的结果却是一些很奇怪的数字。得出这些奇怪答案的原因是,计算机缺少足够的小数位来完成正确的运算。2.0e20是 2后面有20个0。如果把该数加1,那么发生变化的是第21位。 要正确运算,程序至少要储存21位数字。而float类型的数字通常只能储存按 指数比例缩小或放大的6或7位有效数字。在这种情况下,计算结果一定是错 误的。另一方面,如果把2.0e20改成2.0e4,计算结果就没问题。因为2.0e4 加1只需改变第5位上的数字,float类型的精度足够进行这样的计算。