数据是指能够输入到计算机中,并能够被计算机识别和加工处理的符号的集合,是程序处理的对象。所处理的数据可能很简单,也可能很复杂,数据之间存在某种内在联系。为了方便处理这些数据,计算机程序设计语言需要提供一种数据机制以便在程序中更好地表示它们,从而反映出数据的有关特征和性质。 C语言采用这样一种数据机制:把要处理的数据对象划分为一些类型,每个类型是一个数据值的集合。数据类型是按被定义变量的性质、表示形式、占据存储空间的多少、构造特点来划分的。为此C语言一方面提供了一组基本数据类型,如int、char、float、double等,用于对基本数据的表示和使用:另一方面提供了数据构造机制,该数据构造机制提供一组可以由基本数据类型或数据构造更复杂的数据类型或数据的手段。反复使用这些手段可以构造出任意复杂的数据结构,以满足复杂数据处理的需要。 C语言具有非常丰富的数据类型,包括基本数据类型、构造数据类型、指针类型和空类型,见下表。本次主要介绍基本数据类型,一是因为基本数据类型是构造其他数据类型的基础;二是不希望冗长繁杂的数据类型介绍影响读者程序设计方法的学习和程序设计能力的培养。其他各种数据类型将在后面陆续进行详细介绍。
数据类型 | 关键字 | 变量定义实例 | ||
基本类型 | 整型 | 基本整型 | int | int a; |
长整型 | long | long int a;或long a; | ||
短整型 | short | short int a;或short a; | ||
无符号整型 | unsigned | unsigned int a; unsigned long b; unsigned short c; | ||
实型(浮点型) | 单精度实型 | float | float a; | |
双精度实型 | double | double a; | ||
长双精度实型 | long double | long double a; | ||
字符型 | char | char a; | ||
枚举类型 | enum | enum response{no,yes,none}; enum response answer; | ||
构造类型 | 数组 | — | int score[10]; char name[20]; | |
结构体 | struct | struct date { int year; int month; int day; } struct date d; | ||
共用体 | union | union { int class; char position[10] }category; | ||
指针类型 | — | int*p | ||
空类型 | void | void sort(int array[],int n); |
基本数据类型
基本数据类型最主要的特点是,其值不可在分解为其他类型,并且基本数据类型是由系统预先定义好的。C语言的基本数据类型包括整型、实型、字符型和枚举类型。没有小数部分的数就是整型,而有小数部分的数则是实型(也称浮点型),字母或者符号更广泛的说是字符类型。
1.整型数据 在C语言中,整型是比较常用的数据类型。针对不同的用途,C语言提供了多种整数类型,可分为基本整型(int,简称“整型”)、短整型(short)和长整型(long)。上述类型又分为有符号型(signed)和无符号型(unsigned),即数值是否可以取负值,因此整型数据可细分为6种。各种整型数据占用的内存空间大小不同,取值范围也不同,如下表(以Code::Blocks环境为例)
类型名称 | 类型说明符 | 所占字节数 | 取值范围 |
有符号基本整型 | [signed] int | 4 | -2147483648~+2147483647 ~ |
有符号短整型 | [signed] short [int] | 2 | -32768~+32767 ~ |
有符号长整型 | [signed] long [int] | 4 | -2147483648~+2147483647 ~ |
无符号基本整型 | unsigned [int] | 4 | 0~4294967295 0~ |
无符号短整型 | unsigned short [int] | 2 | 0~65535 0~ |
无符合长整型 | unsigned long [int] | 4 | 0~4294967295 0~ |
注 [ ]内的关键字可以省略。
需要说明的是,C语言没有具体规定以上各类数据在内存中所占的字节数,只要求long≥int≥short。具体所占的字节数与机器及系统有关。例如,int类型,表3.9中所列int类型数据在64位系统中Code:Block环境下占4个字节,但是在TurboC下int类型数据只占2个字节。编程时,可以用运算符sizeof0求出所使用环境中int类型数据究竟占用多少字节。 数值是以补码(complement)表示的。一个正整数的补码和该数据的原码(即该数的二进制形式)相同。求负数的补码的方法是,将该数的绝对值的二进制形式,按位取反再加1。例如,求-10的补码:取-10的绝对值10;10的绝对值的二进制形式为1010;对1010取反得1111111111110101(以2字节为例);再加1得1111111111110110。 可知整数最左面的一位数字是表示符号的,该位为0,表示数值为正,为1则表示数值为负。
2.实型数据
在多数情况下使用各种整数类型就可以满足需求,然而,生活中还会涉及相邻整数之间的数,如财务、学生成绩和数学计算中经常要使用实数类型。C语言中实型包括单精度实型(float)、双精度实型(double)和长双精度实型(longdouble)。同样,存储实型数据所占字节数也与系统有关,实型数据的有效数字位数和数值范围由具体实现的系统决定。常用的C语言环境中实数类型的占用空间、取值范围见下表。
类型名称 | 类型说明符 | 所占字节数 | 有效数字 | 取值范围(绝对值) |
单精度实型 | float | 4 | 约6或7位 | ~ |
双精度实型 | double | 8 | 约15或16位 | ~ |
长双精度实型 | long double | 12 | 约18或19位 | ~ |
不同于整型数据的存储方式,实型数据按指数形式存储,分为小数部分(尾数)和指数部分(阶码),如实数N可以表示为,如下图所示:
实型数据的存储方式
例如,实型数据-101.1001B,先转换成规范的指数形式,对应的指数符号为0,指数数值为11;小数符号为1,小数数值为1011001。指数部分与小数部分各占多少二进制位,用原码还是补码形式存放,都与具体的系统有关。 实型数据的存储空间是有限的,所以精度也是有限的,有效位数以外的数字将被舍去,因此会存在误差。
3.字符型数据
在数据处理中,C语言还有一种基本类型——字符类型,类型说明符为char。字符型数据只占1个字节,只能存放1个字符,无法存放多个字符组成的字符串。 字符型数据在存储时并不是将字符本身存放到内存中去,而是将该字符对应的ASCI码值转换成二进制形式存放到存储单元中。由于它与整型数据的存储方式类似,在ASCII码取值范围(1个字节,0~255)内,字符型数据和整型数据可以通用。字符型数据和整型数据之间可以进行算术运算,一个字符型数据可以按字符形式输出也可以按整数形式输出,这给字符处理带来很大的灵活性。
4.枚举类型数据
枚举类型是用标识符表示的有限个整数常量的集合,是指将变量的值一一列出来,变量的值只在列举出来的值的范围内(将在10.5节中介绍)。
构造数据类型
C语言的基本数据类型并不能满足实际应用中的所有需求,用户可以利用整型、实型、字符型这些基本数据类型构造满足需要的数据类型,即构造类型。它包括数组类型、结构体类型和共用体类型。 数组是由一系列相同类型的数据元素构成的,并且是按照一定顺序组织在一起的一个数据集合。例如,人们利用计算机来处理学生成绩、管理每月的销售额等。对于这些大量相互关联的数据,利用数组能够有效方便地进行处理。 在实际问题中,一组数据也可能具有不同的数据类型。例如,一个学生的信息记录中,姓名应为字符数组;学号可为字符数组或长整型;年龄应为整型;性别应为字符型;成绩可为实型。显然不能用一个数组来存放这些数据。因为数组中各元素的类型和长度都必须一致。为了解决这个问题,C语言给出了另一种构造数据类型——结构体类型。结构体类型由不同的“成员”组成,每个成员可以是不同的数据类型。结构体类型与共用体类型会在以后进行详细介绍。 共用体类型也是用来描述类型不相同的数据,但与结构体类型不同,共用体数据成员存储时采用覆盖技术,共享(部分)存储空间。例如,有一张教师与学生通用的表格,教师的数据有姓名(char)、年龄(int)、身份(char)、教研室(char)4项,学生的数据有姓名(char)、年龄(int)、身份(char)、班级(int)4项。可以采用覆盖技术使用教研室(char)和班级(int)共享存储单元。
其他数据类型
1.指针类型
指针是一种特殊的数据类型,也是一种很重要的数据类型。指针的值指的是内存中的地址。指针的使用非常灵活,可以有效地表示各种复杂的数据结构。指针的定义和使用将在第9章进行详细介绍。
2.无类型
C语言中无类型用void表示,一般用于描述指针以及作为不返回值的函数的返回值类型。无类型的第一个用途是定义指针时用作指针的类型,表示该指针可以指向任何类型,但它不同于空指针;第二个用途是表示函数的返回值类型,调用函数时,通常应向调用者返回一个函数值,这个返回的函数值是具有一定的数据类型的,应在函数定义及函数说明中加以说明。也有一类函数在调用后并不需要向调用者返回函数值。对于那些确实不需要返回值的函数,可以将类型说明为void类型。