1、 12 第 2章 数 据 类 型 我们知道计算机处理的对象就是数据,然而不是所有的数据计算机都能直接处理。在计算机高级语言中能直接处理的数据类型称为该语言的数据类型。本章主要讨论 C 语言的数据类型。 2.1 C数据类型概述 什么是计算机的数据类型?这是我们首先要明确的一个问题。 数据类型 (data type)是一个值的集合和定义在这个集合上的一组操作的总称。例如 C 语言中的整数类型 int,它的值的集合为区间 minint, maxint上的整数 (minint、 maxint 是依赖特定计算机的最小、最大整数 );定义在 其上的一组操作为:加、减、乘、整除和取模等。数据类型体现了数据结
2、构的特点,一种高级语言提供的数据类型越丰富,其直接描述简单数据结构和组织复杂数据结构的能力就越强。 C 语言提供的数据类型较一般高级语言丰富, C 语言除提供整型、字符型和实型等基本数据类型外,还提供了数组、结构体、共用体和指针等数据类型。利用这些数据类型能便捷地描述较复杂的数据结构 (如常用的链表、二叉树、栈等动态存储分配的数据结构 )。 C的数据类型如下: C语言中的数据有常量和变量之分,类似于数学中的常量和变量。 2.2 常 量 常量是指程序运行过程中其值不能被改变的数据对象。常量可以有不同的类型,如: 78,0, 96 为整型常量; 76.6, 12.4 为实型常量; a, A为字符型
3、常量; a、 C Language是字符串常量等。 2.2.1 整型常量 整型常量即整型常数。 C 语言整型常数可用三种表示方式: 数据类型 空类型 指针类型 基本类型 整型 字符型 实型 (即浮点型 ) 枚举类型 构造类型 数组类型 结构体类型 共用体类型 13 (1) 十进制整数。如 124, 234, 23, 0 等。 (2) 八进制整数。以 0 开头的数是八进制数。如 0234 表示八进制数 (234)8,它等于十进制数 156。 (3) 十六进制整数。以 0x或 0X 开头的数是十六进制 数。如 0x234 表示十六进制数 (234)16,它等于十进制数 564。 例 2.1 整型常
4、量的表示。 #include void main() int a, b, c; a50; / a为十进制整数 50 b032; / b 为八进制整数 32 c0x5b; / c为十六进制整数 5b printf(ad, bd, cdn, a, b, c); /以十进制整数形式输出 a, b, c的值 运行结果如下: a50, b26, c91 2.2.2 实型常量 实数在 C语言中又称浮点数。实数有两种表示形式: (1) 十进制数形式。它由数字和小数点组成 (注意必须有小数点 )。如 0.678, .678, 678.0,678., 0.0都是十进制数形式。 (2) 指数形式。如 54.0e3
5、 或 54E3 都代表 54.0103。但注意字母 e(或 E)之前必须有数字 ,且 e 后面指数必须为整数,如 e6, 3.2e7.5, .e9, 5e等都是不合法的指数形式。 2.2.3 字符型常量 1字符常量 C 语言的字符常量是用单引号 (即撇号 )括起来的一 个字符。如 a, A, #, ?等都是字符常量。注意, a和 A是不同的字符常量。 C 语言中有些控制字符 (又称非显示字符 )是无法直接用字符常量形式表示的。例如,前面已经遇到过的,在 printf函数中的 n,它代表一个“换行”符,就是一个难以用字符常量表示的控制字符。 C 语言规定用一种特殊形式表示控制字符,即以一个“ ”
6、开头的字符序列。因为“ ”后面的字符已不再是原来该字符的作用而转为新的含义,因而称为转义字符。如 n中的“ n”不代表字母 n,而作为“换行”符。 C语言的转义字符如表 2-1所示。 表 2-1 转义字符 字符 功 能 字符 功 能 n 换行 a 响铃 t 横向跳格 (跳到下一个输出区 ) 反斜杠字符 v 竖向跳格 单引号字符 b 退格 双引号字符 r 回车 ddd 1到 3 位 8进制数所代表的字符 f 走纸换页 xhh 1到 2 位 16进制数所代表的字符 14 例 2.2 转义字符的验证。 #include void main() printf( ct deratYb=n); /为了反映
7、空格的个 数,用 表示空格 printf(376); 第一个 printf 函数先在第一行左端开始输出“ c”,然后遇到转义字符 t,它的作用是跳格,即跳到下一个“输出区”,在我们所用系统中一个“输出区”占 8 列。“下一个输出区”从第 9 列开始,故在第 911 列上输出“ de”。下面遇到转义字符 r,它代表“回车 ” (不换行 ),当前输出位置移至本行行首 (第 1列 ),输出字符 a,然后遇转义字符 t再使当前输出位置移到第 9 列,输出字符 Y,输出 Y后当前输出位置是第 10 列。然后遇转义字符 b,它的作用是“退格”,使当前输出位置回退到第 9 列,接着输出 =。下面是转义字符
8、n,它的作用是“回车换行”,当前输出位置移至下一行的行首。第二个 printf 函数是输出转义字符376,即字符 。 程序运行时,在打印机上得到如下结果 (为了清晰地反映空格个数和对位关系,这里用 表示空格,并全部 使用全角字符 ): ¥ 在显示屏上看到的结果是: 这是由于转义字符 r使当前输出位置回到本行行首,自此输出的字符 (包括空格和转义字符 t导致 的跳格所经过的位置 )将取代原来屏幕上显示的字符;转义字符 b导致退格,使当前输出位置左移一列,该位置上原来屏幕上已显示字符也将被新输出的字符所取代。实际上,屏幕上完全按程序要求输出了全部的字符,只是因为在输出前面的字符后很快又输出后面的字
9、符,在人们还未看清楚之前,新的已取代了旧的,所以误认为未输出应输出的字符。而在打印机输出时,不像显示屏那样会“抹掉”原字符,人们可以从打印机的运动过程观察到所有的输出过程和结果。如在第 9列上输出字符 Y后又输出字符 =,两字符重叠打印成“¥”。 2字符串常量 字符 串常量由一对双引号括起来的字符或转义字符序列构成。如 welcome、 a、$567.88、 I am a student.n、 nn等都是字符串常量。 注意: a是字符常量, a是字符串常量,二者不同,不要混淆。 2.2.4 符号常量 符号常量是在程序 (或程序的一部分 )中指定用一个符号 (标识符 )代表一个常量。请看下面的例
10、子: 例 2.3 符号常量的使用。 #include #define PI 3.14159 /* 定义符号常量 PI */ void main() 第 9 列 第 9 列 15 float radius, area; radius2.0; areaPI*radius*radius; printf(Areafn, area); 程序中用 #define 命令行定义标识符 PI 代表常量 3.14159,此后凡在此文件中出现的 PI都代表 3.14159,可以和常量一样参与运算。程序运行结果为: Area12.566360 说明: (1) 我们用符号 PI代替常量 3.14159,使程序更易理解,
11、可读性好。 (2) 当需要修改 PI的值时只需要改一处即可,方便又不易出错 。 (3) 定义符号常量要用 #define命令,一般格式是: #define 符号常量标识符 常量 这是一种“预编译命令”。有关 #define 命令的详细用法参见第 12 章。 注意: 符号常量不同于变量,它的值在其作用域 (在本例为主函数 )内不能改变,也不能再被赋值。如使用以下赋值语句给符号常量 PI赋值是错误的。 PI3.1415; /* 错误的赋值语句 */ 习惯上,符号常量名用大写,变量名用小写,以示区别。 2.3 变 量 变量是指在程序运行过程中其值可以被改变的数据对象。实质上,变量是程 序中的数据连同
12、其存储空间的抽象。 C 语言规定变量必须先定义 (也可称为声明 )后使用。所谓定义变量就是通过 C 语句要求系统为该变量分配一个适当的存储单元,供存放数据使用。 例如, C 语句“ int x;”就是向系统申请一个能存放 int(基本整数 )型数据的存储单元,如图 2-1(a)所示。 系统分配的这个单元只能存放 int型的数据,且每一个时刻只能存放一个, x 为这个单元的名字,我们称为变量名。 变量定义好后,我们可以通过变量名对该单元进行存取数据。如 C 语句“ x25;”就是把25存入变量 x 中,其结果如图 2-1(b)所示。如果再执行 C 语句“ x128;”将把 128存入变量x中,其
13、结果如图 2-1(c)所示,此时变量 x 的值就改变为 128,而不再是 25。 理解 C 语言的变量时应该注意以下几点: (1) 一个变量应该有一个名字,称为变量名,如变量名 x。 (2) 一个变量在内存中占据一定大小的存储单元,可以通过变量名对该存储单元存取变x x x (a) (b) (c) 图 2-1 变量的存储单元 25 128 16 量的值,如 128为变量 x的值。 (3) 变量是有类型的,不同类型的变量分配不同大小的存储空间,存放不同类型的数据 。如C语句“ int x;”定义的是一个 int型变量,它所对应的存储单元是 2个字节。 (4) 所谓的变量应该包括变量名、存储单元、
14、变量的值几部分内容。 2.3.1 标识符的命名规则 与其他高级语言一样,用来标识变量名、符号常量名、函数名、数组名、类型名、文件名等的有效字符序列称为标识符。简单地说,标识符就是一个名字。 C 语言是大小写敏感的,即大写和小写字母认为是不同的字母。例如变量名 name 和NAME表示不同的名字。 C语言标识符的命名规则是: (1) 标识符只能由 26 个字母、数字和下横线“ _”组成,且数字不能作为标识符的第一个字符。 (2) C 语言中标识符的长度 (字符个数 )无统一规定,随 系统而定。在 Turbo C 中,一个标识符的前 31个字符在程序中是有效的,也即是说,它们可以相互区别。 (3)
15、 标识符中间不能有空格。 (4) C 语言的关键字不能作为标识符。 例如, price、 velocity、 a3、 interest、 m_iNumber 等都是合法的变量名,而 101、 NO.1、S / 定义 2个 unsigned int 类型的变量 int iLength, iWidth, iHigh; / 定义 3个 int类型的变量 float fArea; / 定义 1 个 float类型的变量 char cSex, cType; / 定义 2个 char类型的变量 说明: (1) 空类型 (void类型 )仅仅是具有数据类型的形式,不具备其他数据类型的属性,它一般是用来声明函
16、数的类型,表 示函数不需要返回值。 (2) 字符串只有常量的概念,没有直接的变量概念。但是,可以通过字符数组和字符指针变量来实现字符串变量的作用 (详见第 6 章和第 8 章 )。 2变量的初始化 定义一个变量后,系统为所定义的变量按数据类型的要求分配一个一定大小的存储单元,这时该存储单元所存放的值 (变量的值 )一般是一个不确定的值 (随机值 )。此后,可以用赋值运算符“ ”给变量赋值。 例如: unsigned unMyAge; / 变量的定义 18 int iLength, iWidth; unMyAge18; / 变量赋值 iLength12; iWidth10; 也可以在定义变量的同
17、时给变量赋值,称为变量的初始化。例如: unsigned unMyAge18; / 变量的定义并初始化 int iLength12, iWidth10; 可见,一条变量初始化语句相当于前面介绍的变量定义、给变量赋值两条语句,它们的效果完全一样。系统都是先给变量分配一个存放整数的内存单元,然后将一个整数值赋给该变量 (存储单元 )。 3变量或类型长度运算符 sizeof( ) C语言提供的运算符 sizeof( )是用来求 C 语言的类型或变量所分配存储单元的长度 (字节数 )。例如, sizeof(int)或 sizeof(iWidth)的值为 2, sizeof(float)或 sizeof
18、(fArea)的值为 4,说明int型的数据在计算机内存占 2个字节,而 float 型的数据占 4个字节。 2.3.3 整型变量 基本数据类型的变量包括整型变量、实型变量、字符型变量和枚举类型变量 (在第 11 章中讨论 )。整型变量可分为基本型、短整型、长整型三种,分别是: (1) 基本型,类型标识符为 int; (2) 短整型,类型标识符为 short int 或 short; (3) 长整型,类型标识符为 long int 或 long。 它们又区分为有符号 (signed)和无符号 (unsigned)两大类。对于有符号数,存储单元的最高位用来存储符号, 0表示 , 1 表示 ;对于
19、无符号数,存储单元中全部二进制位 (bit)用作存放数本身,而不包括符号。无符号型变量只能存放不带符号的整数,如 23、 507 等,而不能存放负数,如 23、 98。 如果整型量在内存中占 2个字节 (16位 ),则 int型变量存放数的范围 为3276832767,而 unsigned int 型变 量存放数的范围为 065535。概括起来,整型变量有: C 标准没有具体规定以上各类数据所占内存字节数,各种机器处理上有所不同,一般以一个机器字 (word)存放一个 int 型数据,而 long型数据的字节数应不小于 int型, short 型不长于 int 型。 以 IBM PC 为例,整
20、型数的表示范围如表 2-4所示。用户可根据数的范围来选用。 整型变量 长整型 (long) 基本整型 (int) 短整型 (short) 无符号型 无符号整型 (unsigned int) 无符号短整型 (unsigned short) 无符号长整型 (unsigned long) 19 表 2-4 整型数据的表示范围 类型标识符 所占位数 数的范围 int 16 32 76832 767 即 215(2151) short int 16 32 76832 767 即 215(2151) long int 32 2 147 483 6482 147 483 647 即 231(2311) un
21、signed int 16 065 535 即 0(2161) unsigned short 16 065 535 即 0(2161) unsigned long 32 04 294 967 295 即 0(2321) 例如: int a2; short int b32765; long int c2; unsigned int d65534; unsigned short e32765; unsigned long f0xABCDEF; 整型数据初始化后,系统分配给相应变量的存储单元及整型数据的存储结构如图 2-2 所示。注意:变量 a、 b、 c的最高位 (即最左边一位 )为符号位。 2.
22、3.4 实型变量 C语言的实型变量分为单精度型 (float 型 )、双精度型 (double 型 )和长双精度型 (long double型 )三类。对每一个实 型变量都应在使用前加以定义。如: float x, y; / 定义 x、 y为单精度实型变量 double z; / 定义 z为双精度实型变量 实数的有效数字位数和数值的范围随机器系统而异。在 IBM PC 中,一个 float 型数据在内存中占 4个字节 (32 位 ),一个 double 型数据占 8 个字节 (64位 ),一个 long double型数据占10个字节 (80位 )。单精度实数提供 67 位有效数字,双精度实数
23、提供 1516 位有效数字,长双精度实数提供 1819位有效数字;单精度实数的数值范 围约为 3.410383.41038,双精度实数范围约为 1.7103081.710308,长双精度实数范围为 3.41049321.1104932。 应当说明,实型常量不分 float 型和 double 型。一个实型常量可以赋给一个 float 型或double型变量,根据变量的类型截取实型常量中相应的有效位数字。例如: float a; 图 2-2 整数的存储 a b c d e f 1111 11 11 11 11 11 10 int 型 (2) 01 11 11 11 11 11 11 01 sho
24、rt 型 (32765) long型 (2) 11 11 11 11 11 11 11 10 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 10 unsigned int型 (65534) 01 11 11 11 11 11 11 01 unsigned short 型 (32765) unsigned long型 (0xABCDEF) 11 00 11 01 11 10 11 11 00 00 00 00 10 10 10 11 20 a222222.222; 由于 float 型变量 a 只能接收 7 位有效数字 (即 a222222.2),因此
25、最后两位小数不起作用。如果 a 改为 double型,则能全部接 收上述 9 位数字并存储在变量 a 中。 2.3.5 字符型变量 1字符型变量 字符型变量 (简称为字符变量 )可以存放单个字符型数据。例如: char cl, c2; 表示 cl 和 c2为字符型变量,各可以存放一个字符。我们可以用下面的语句给它们赋值: cl=a; c2=b; 注意: (1) 系统分配一个字节大小的单元给字符型变量。 (2) 对于字符型变量,存储单元中存放的是字符的 ASCII码。如 c1、 c2 的存储形式如图2-3 所示。 (3) 由于在内存中,字符型数据是以 ASCII 码形式存储的,它的 存储形式与整
26、数的存储形式相类似,所以 C 语言的字符型数据和整型数据可以通用。因此, C 语言中的字符数据和整型数据可以相互赋值;并且字符数据可以以字符形式输出,也可以以整数形式输出。 例 2.4 字符型数据的整型处理。 #include void main() char c1, c2, c3; c1a; c297; c3c132; printf(c, c, c, c1, c2, c3); printf(d, d, d, c1, c2, c3); 运行结果 如下: a, a, A 97, 97, 65 分析:其中 c1、 c2、 c3 被定义为字符型变量,然后给 c1、 c2 分别赋予字符常量 a、整数
27、97,而 C 语言对于 a,和 97 在内存中的存储形式是完全一样的; c3 赋予一个算术表达式c132(其值为 65,对应字符为 A)。 上述程序中从 a 到 A的变换是 c3c132。 C 语言对字符数据作这种处理使程序设计增大了自由度,因而对字符作各种转换就比较方便。 0 1 1 0 0 0 0 1 c1 0 1 1 0 0 0 1 0 c2 图 2-3 字符数据的存储形式 21 提醒读者注意,将一个整数赋给一个字符型变量时,该整数应在 0255范围内,否则会产生溢出。 (4) 无符号字符型标识 符 unsigned char 的使用。在 Turbo C 系统中,将字符型变量所占用的字节
28、的最高位当成符号位,或者说把字符处理成带符号的整数。如: 字符 a: 01100001 它的最高位 (8位中最左一位 )为 0,此字符按整数形式输出时就输出一个正整数,它的值就是ASCII码的值 97。 字符 376: 11111110 它的最高位为 1,内存中被视为负数,如按字符形式输出则是系统中相应的图形字符,在 IBM PC上为字符 ;如将它按整型输出,输出结果是 2,因为 2 的补码为 11111110。 如果字符型变量说明为 unsigned char 型数据,即无符号字符型变量,其最高位不作为符号位。 例 2.5 无符号字符数据。 #include void main() unsi
29、gned char c376; printf(c, d, c, c); 运行结果如下: , 254 这是由于 11111110 的十进制数值为 254。 2字符数据与字符串数据的区别 字符数据与字符串数据不仅仅是书写形式和字符的个数不同,它们在内存中的存储形式也是有较大区别的。 在 C语言中,每一个字符串的结尾系 统自动加上一个字符串结束标志 0,以便系统据此判断字符串是否结束。 0是一个 ASCII 码为 0 的字符,是“空操作字符”,即它不引起任何控制动作,也不是一个可显示的字符。 我们可通过比较 a、 a、 HELLO在内存中存储形式的不同 (如图 2-4 所示 ),了解字符常量与字符串常量的区别。其中,字符 a占 1个字节的存储空间,字符串 a占 2 个字节的存储空间,字符串 HELLO占 6 个字节的存储空间。 例如: char c1, c2, c3; c1a; a 01100001 01100001 a 00000000 0 a L HELLO 01001000 H 01000101 E 01001100 L 01001100 01001111 O 00000000 0 图 2-4 字符与字符串的存储比较