购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.1 C语言基本数据类型

“程序=数据结构+算法”,算法很容易理解,就是解决问题的思路和步骤,那数据结构是什么呢?一个程序中肯定要用到数据,而数据有简单的,也有复杂的,如何对这些数据进行设计和定义,如何进行数据的存储和访问,这些数据间有着什么样的关系,这些都是数据结构要考虑的事情。可见,数据对于一个程序是非常重要的。C语言里有不少数据类型,按照先易后难的原则,本节主要讲述C语言中的基本数据类型。

C语言的基本数据类型有三类:整型、实型与字符型。

2.1.1 整型

整型,顾名思义,整数类型,也就是不带小数点的数值类型。是不是太简单了?不过整型按占用内存大小和所能表示的数值范围又可分为短整型、标准整型、长整型和长长整型,分别用关键字“short int”“int”“long int”“long long int”表示。为什么要分成这么多的类型呢?想要理解这个问题,必须先了解一下内存存储相关的问题,因为这里涉及了内存大小,所以下面简单介绍一下二进制、位和字节的相关知识。

1.二进制、位和字节

我们的日常生活中离不开数字,但生活中通常所使用的都是十进制的数,而计算机只能处理二进制数,所以要把十进制数转换成相对应的二进制数,计算机才能处理。

十进制的规则是逢十进一,它的每一位都是由0~9的数字构成。对应的二进制的规则就是逢二进一,它的每一位只能由0或1构成。此外,在C语言中除了二进制,还有可能会用到八进制和十六进制。所以对于“10”,如果它是十进制数,就是10;如果它是二进制的话,那么它所对应的十进制数就是2;若是八进制,对应的十进制数就是8;若是十六进制,则其对应的十进制数就是16。下面列出十进制数0~15所对应的二进制、八进制和十六进制数值。

对于十进制整数23,转换成对应的二进制码为10111,二进制码里的每个“0”或“1”称为一个二进制位(Bit),简称位。在两个位中左为高位,右为低位。

内存的最小存储单位为字节(Byte),1字节有8位(即1字节可以存放8个二进制的“0”或“1”),所以要把整数“23”存放在内存中至少需要1字节的空间,位数不够8时前面补0。即十进制数“23”对应的8位二进制码为“0001 0111”,如图2.1所示。

图2.1 存储在1字节内存中的十进制数“23”

在这8位中,位序为7的位是最高位,位序为0的位是最低位,其中最高位是作“正负”的标记位来使用的,称为符号位,即符号位的位值为“0”表示正数,为“1”表示负数,剩余的7位用于存储整数所对应的二进制码,称为数据位。所以1字节所能表示的取值范围从–128(二进制码为“1000 0000”)~127(二进制码为“0111 1111”),共256个。

要想把一个更小或更大的整数存储到内存中,8位就显然无能为力了,必须使用更多的内存空间,例如2字节就拥有16位,可表示的取值范围变成从–32768(二进制码为“1000 0000 0000 0000”)~32767(二进制码为“0111 1111 1111 1111”),共65536个,扩大了256倍。

大家可以想象一下,如果C语言中只有一种整数类型的话,让其使用多少字节的内存比较合适呢?假如使用的内存字节数多,则能表示的数值范围大,但如果用它来存放一些小数值,就会造成内存的浪费;反之,如果使用的内存字节少,可能又存放不了比较大的数值,无论怎样都不能两全其美。

现在明白为什么把整型分为这么多的类型了吧,根据不同的数值大小,使用不同大小字节的内存空间,既不浪费内存空间,又能放得下相应的数值,真正做到“物尽其用”。表2.1是本书的开发环境下各种整型的内存大小和所能表示的取值范围。

表2.1 整型的内存大小和取值范围

一个整型“摇身一变”成了四种类型,是不是挺有趣?其实它还可以再变出四种类型。这次新变出的四种新类型和之前的四种非常类似。

2.无符号整型

前面讲到把一个整数转换成对应的二进制码,其中的最高位是用来标记正负数的符号位。这时会不会有读者突发奇想:“那如果不要这个符号位,把它也变成数据位,用于存放整数的二进制位,不是就能多出1倍的取值范围吗?”不得不佩服大家的聪明,也很有想象力,但不够准确。

如果没有了表示正负整数的符号位,那么就没有了负数的表现能力,所存储的全部视为正整数。最终的结果就是正整数的取值范围扩大了一倍,但总的取值范围没变。例如1字节所能表示的取值范围从0(二进制码为“0000 0000”)至255(二进制码为“1111 1111”),还是256个;2个字节的取值范围从0(二进制码为“0000 0000 0000 0000”)至65535(二进制码为“1111 1111 1111 1111”),还是65536个。

对于这种没有符号位,全是数据位的整数类型,我们称之为无符号整型,它的关键字为“unsigned”。之前所讲的四种整数类型都是有符号整型,它们也有个关键字“signed”,不过通常不用写,也就是默认的整型就是有符号的,若想使用无符号的整型,前面加上“unsigned”关键字即可。在本书的开发环境下,各种无符号整型的内存大小和取值范围如表2.2所示。

表2.2 无符号整型的内存大小和取值范围

2.1.2 实型

整数类型讲完应该讲小数类型了。C语言把这种带小数点的数值类型称为实型或浮点数类型。虽然实型与整型只有一字之差,但它却有和整型完全不同的内存存储方式,通过上一节的学习,我们知道了有符号整型的最高位是符号位,其他的都是数据位,对于无符号整型来讲,全部都是数据位。而实型却是分为三段进行存储的:符号位、阶码位、数据位。其中最高位是符号位,中间部分是阶码位(或称指数位),最后部分是数据位(或称尾数位),如图2.2所示。

图2.2 实型内存存储示意图

这种类似于科学计数法的内存存储方式,能够轻松存储一个比较大的数值,并拥有非常大的取值范围,但是在数值的精度上可能会有所损失,毕竟鱼与熊掌不可兼得。由于实型的这种特殊的内存存储方式,导致在处理速度上没有整型的快,所以如果程序中不涉及小数的话,尽量还是选用整型。

实型按照内存大小分为单精度浮点数类型、双精度浮点数类型和长双精度浮点数类型,关键字分别为“float”“double”和“long double”。其中单精度浮点数类型,内存大小为4个字节,即32位(符号位1位,阶码位8位,数据位23位);双精度浮点数类型的内存大小为8字节,即64位(符号位1位,阶码位11位,数据位52位);长双精度浮点数类型是相对较新的一种实型,它拥有更大的数值表现和存储能力,但由于C标准并未对它的内存大小有所规定,所以在不同的系统和编译器上,可能被实现为各种不同字节大小的版本。实型的内存大小和取值范围如表2.3所示。

表2.3 实型的内存大小和取值范围

2.1.3 字符型

也许读者会有疑问,为什么没有1字节大小的整型呢?其实是有的,只不过通常我们把它称为字符型,关键字为char。也就是说,字符型就是1字节的整型。那为什么要把它称为字符型呢?为了能够在程序中使用字符,最初C语言规定将1字节的整型作为字符来使用,更确切地说,是将0~127这128个正整数作为字符使用,这就是大名鼎鼎的ASCII码(美国信息交换标准代码)。

ASCII码中定义的全是英文字符,例如大写和小写的英文字母、数字字符、标点符号以及特殊的控制字符。例如用整数10表示换行字符,整数32表示空格字符,整数48~57表示数字字符0~9,整数65~90表示大写字母A~Z,整数97~122表示小写字母a~z等等。这里需要注意的是数字字符“0”和整数0是不同的概念。数字字符“0”对应的整数是48,而整数0也有一个对应的英文字符,它是空字符,通常用它来表示一个字符串的结束。ASCII码中的其他的一些常用字符见表2.4。

表2.4 ASCII常用字符与整数对照表

既然字符型就是1字节的整型,我们完全可以把字符型当成整型来使用。字符型是不是也分有符号和无符号呢?答案是肯定的。默认的字符型就是有符号的,取值范围为–128~127。ASCII码就采用里面的正数部分,若在字符型的前面加上“unsigned”关键字,那么就是无符号的字符类型了,其取值范围为0~255,具体见表2.5。

表2.5 字符型内存大小和取值范围

2.1.4 设置类型别名

在C语言中,允许使用“typedef”关键字来设置类型别名。所谓设置类型别名,就是给数据类型起一个新的名字。设置类型别名的格式为:

设置类型别名之后,新类型名具有与原类型名相同的数据类型,用户可以随意选择使用新类型名和原类型名,效果是一样的。既然一样,那设置类型别名有什么好处呢?

1.简化长类型名

C语言中,有些数据类型的名字比较长,很容易造成书写错误。若给这样的数据类型设置一个简短的别名,就能减少书写上的错误。例如:

通过typedef给unsigned int类型设置一个简短的别名uint,后面代码中需要使用unsigned int的地方,可以使用uint,是不是方便多了,类型名的字符少了,书写错误自然也会减少。

2.便于代码维护

例如我们给short类型设置一个别名“DATATYPE”,并在代码中都使用这个别名:

过了一段时间后,发现short类型太小,不够用,想换成更大的类型int,那么只需改动设置类型别名的地方:

现在代码中所有的DATATYPE都表示为int类型了。是不是很方便?若是没有设置类型别名,就得到代码中一一查找要修改的地方,对代码量大的程序来说工作量很大。

3.扩展类型信息

举个例子,在保存某人的基本信息的代码中,如果看到一个int类型的变量,怎么能知道这个变量所表示的是什么呢?是人的身高、体重还是年龄?这时可以给int类型设置类型别名:

在代码中,变量的类型使用Age,这样一下就能明白这个变量保存的是一个人的年龄。 UIQ8OS8y8TcD4/VMXlDXRM1pLrJU62ScT7nZG62/gRWRD7Nu8M1vZzaXb6vjn6Cn

点击中间区域
呼出菜单
上一章
目录
下一章
×