第2篇 基础篇
第3章 基本数据类型
C语言要处理的对象是数据,其中整数、实数、字符是要处理的的最基本的数据,而其他类型的数据都是由这些基本数据组合而成的。本章主要讲解C语言中的基本数据类型:整型、实型和字符型。
3.1 数据类型的定义及分类
一个人的年龄需要使用整数表示,如张三的年龄是27岁。一个学生的平均成绩需要使用带小数的数据表示,如周杰的各门功课的平均成绩是87.5。一个人的性别需要使用字符表示,如刘艳的性别是女。这些数据分别对应于C语言中的整型、浮点型(也称实型)和字符型。
C语言中的数据类型划分如图3.1所示。
1.基本类型
基本类型是指该类型不可再分。基本类型包括整型、浮点型、字符型和枚举类型。本章主要讲解整型、浮点型、字符型,枚举型将在后面的章节讲到。
图3.1 数据类型的分类示意图
1)整型数据
在C语言中,整型数据可以用十进制、八进制和十六进制表示。其中,八进制整数以0开头,十六进制整数以0x开头。整型数据的几种进制表示如表3.1所示。
表3.1 整型数据的几种进制表示
2)浮点型数据
浮点型数据有两种表示方法:十进制小数表示法和指数表示法。例如,123.89、-2.37、71.24都是十进制小数表示法,3.65e6、6.78E-6、7.92e-12都是指数表示法。需要注意的是,在十进制小数表示法中,小数点前面如果只有0,则可以省略0。例如,0.123可以写作.123。在指数表示法中,e或E前面必须有数字且后面的数必须是整数。例如,e5、1.2e2.3、e2.5都是错误的表示形式。
3)字符型数据
字符型数据是使用一对单引号括起来的一个字符。例如,'A'、'X'、'x'、'a'、'b'、't'都是字符型数据。这里的单引号只是为了表明该数据是字符型数据。注意,'X'和'x'是两个不同的字符。
在C语言中,还有一种特殊的字符──转义字符。转义字符是以反斜杠'\'开头的字符,如第2章中的最简单程序中的'\n'就是转义字符,表示换行。C语言中常见的转义字符如表3.2所示。
表3.2 常见的转义字符
例如,'\101'表示十进制数65对应的字符'A','\0x41'表示十进制数65对应的字符'A'。
4)字符串型数据
字符串型数据是由多个字符构成的数据类型。字符串是由一对双引号括起来的字符序列。例如,"hello word"、"thankyou"、"bye"、"nwu"、"tsinghua"都是字符串类型的数据。需要注意的是,字符串数据中不允许出现双引号(”)和反斜杠(\)。
2.构造类型
构造类型是由基本数据类型组合而成的。构造类型的每一个成员是一个基本数据类型或其他数据类型。构造类型包括数组类型、结构体类型和联合体类型。其中,数组类型可以看成是由若干个变量构成的类型,结构体类型和联合体类型都属于用户自定义的类型,用来表示一些复杂的数据,如教职工情况表中的元素、学生成绩表中的元素。
3.指针类型
指针类型是一种特殊的类型,它表示某个数据的地址。指针类型是C语言的灵魂,它是区别于其他语言的重要特性。通过指针可以很方便地访问内存中的数据,可以大大提高程序的执行效率并使C语言的使用变得更加灵活。
4.空类型
空类型是指数据没有类型,多应用在类型的转换场合,通常是指针类型的转换。
3.2 变量与常量
为了程序设计的需要,需要引入变量和常量。在程序设计过程中,需要将经常变化的数存放在变量中,将不变化的数存放在常量中。变量和常量都是一种容器,它们是存放数据的容器。本节主要讲解变量与常量。
3.2.1 变量
变量是指其值可以改变的量。变量是用来存放数据的内存单元,变量相当于存放物品的容器,数据相当于物品。例如,一个纸盒子里面可以存放鞋子,也可以存放书或其他东西。这个纸盒子就相当于C语言中的变量,鞋子、书则相当于C语言中的数据。一般情况下,一个变量只能存放一个数据。
1.什么是变量
变量是内存储器中的一个存储单元,用来存放数据。一个变量有一个名字,称之为变量名,存放在变量中的数据则叫做变量值。变量的示意图如图3.2所示。
图3.2 变量的示意图
在图3.2中,a是变量名,a中存放了一个数据8,8就是变量值。
2.变量名是一种标识符
变量名就是变量的名字,它是一种标识符。后面将要学到的常量名、数组名、函数名、类型名、文件名也是标识符。C语言规定标识符只能由字母、数字、下划线构成,其中第一个字符必须是字母或下划线。例如,下面是一些合法的变量名,也是标识符:
abc,_abc,a_b2,x2,xyz,a,b,hello,name,num,count,year,month,day
下面是一些非法的变量名,也是非法的标识符:
3abc,a-b,a+b,M.D.,a#b,a<b
注意
在C语言中,大写字母和小写字母被认为是两个不同的字符。例如,Student、student、STUDENT是不同的变量名。一般情况下,变量名用小写字母表示。
3.关键字是一种特殊的标识符
关键字是一种特殊的标识符,而变量名是用户定义的标识符。因此,关键字不能用来作为变量名。C语言中的关键字有32个,如表3.3所示。
表3.3 C语言中的关键字
表中,int、char、float用来说明变量的类型,分别表示整型、字符型和浮点型。
4.定义变量
在C语言中,必须先定义变量,然后才能使用变量。变量的定义形式如下所示。
类型说明符 变量名;
类型说明符是指int、char和float等关键字;变量名由用户自己定义,必须符合标识符的定义。例如,下面是一些合法的变量定义:
01 int a; /*a被定义为整型变量*/ 02 char b; /*b被定义为字符型变量*/ 03 float average; /*average被定义为浮点型变量*/
经过以上变量定义之后,在编译阶段这些变量将会被分配相应的存储单元,由此便可以用来存放相应的数据了。
3.2.2 常量
在程序运行过程中,其值不发生改变的量叫做常量。在C语言中,常量主要有整型常量、浮点型常量、字符常量、字符串常量。常量与变量一样,在使用之前也需要先进行定义。它的定义方式有两种:使用#define定义常量和使用const定义常量。
(1)使用#define定义常量。使用#define定义常量的形式如下:
#define 常量名 常量值
#define、常量名、常量值之间需要使用空格分隔开。常量名也是标识符,一般用大写表示。例如,一个名字为N的常量定义如下:
#define N 20 /*N是常量名,N的值为20*/
在定义常量时,必须为常量指定一个固定的值,该值在程序运行过程中不可以改变。
(2)使用const定义常量。使用const定义常量的形式如下:
const 类型说明符 常量名=常量值
其中,类型说明符是指int、char、float等,常量名与常量值用等号“=”连接。这里的“=”在C语言中被称为赋值符号,即将常量值存放在常量名标识的内存单元中。例如,一个名字为PI的常量定义如下:
const float PI=3.1415926; /*将PI定义为浮点型常量,其值为3.1415926*/
使用#define和使用const定义常量的效果相同。在程序运行过程中,常量的值都不可以改变。需要注意的是,使用#define定义常量时后面不需要使用分号,而使用const定义常量时后面需要使用分号。
下面具体介绍C语言中的各种类型常量。
1.整型常量
定义整型常量可以使用#define和const两种方法。例如,定义一个八进制整型常量M的代码如下:
01 #define M 032 02 const int M=032;
以上两行代码的作用是等价的,即M被定义为常量且其值为八进制整数032。如果定义一个十进制整型常量D,代码如下:
#define D 50
D为整型常量符号,其值为50。以上代码与下面的代码等价:
const int D=50;
2.浮点型常量
浮点型常量的定义方法与整型常量的定义方法类似。例如,使用const定义一个圆周率PI,代码如下:
const float PI=3.1415926;
以上代码与下面的符号定义形式等价:
#define PI 3.1415926
3.字符型常量
使用const定义字符型常量需要使用关键字char。例如,定义一个字符型常量CHAR的代码如下:
const char CHAR='X';
它与以下代码等价:
#define CHAR 'X' CHAR就代表了字符'X'。
注意
使用const定义常量时,需要使用类型说明符int、float、char等说明常量的类型;使用#define定义常量时,则不需要说明常量的类型。
3.3 整型变量
整型变量只能存放整型数据,但是存放在整型变量中的数据可以改变。整型变量有以下几种类型。
(1)基本整型变量。基本整型变量对应于C语言中的关键字int。
(2)短整型变量。短整型变量对应于C语言中的关键字short int。
(3)长整型变量。长整型变量对应于C语言中的关键字long int。
本节主要讲解这3种整型变量的定义、表示范围、存储形式、变量的赋值。
3.3.1 整型变量的定义
C语言中的整型变量根据数据的表示范围可以分为基本整型变量、短整型变量和长整型变量,分别用int、short int、long int表示。整型变量的定义形式根据是否带符号分为带符号整型变量的定义与无符号整型变量的定义。
1.带符号整型变量的定义
带符号整型变量的定义格式如下:
整型类型说明符 变量名列表;
整型类型说明符是指int、short int、long int。变量名列表可以是一个变量名或多个变量名。如果是多个变量名,需要使用逗号分隔开。例如,
01 int a; /*a为基本整型变量*/ 02 short int b; /*b为短整型变量*/ 03 long int c; /*c为长整型变量*/ 04 int x,y,z; /*x、y、z被定义为基本整型变量,使用逗号分隔开*/
其中,短整型变量定义中的short int可以省略int,长整型变量定义中的long int可以省略int。因此,上面代码的第2行和第3行与以下代码等价:
02 short b; /*b为短整型变量,省略了int*/ 03 long c; /*c为长整型变量,省略了int*/
以上定义的整型变量都属于有符号整型,即变量有正负之分。
2.无符号整型变量的定义──使用unsigned
在C语言中,还可以定义无符号整型变量,这种变量中的数据都是正数。它的定义格式是在1.的定义格式前面增加一个修饰符unsigned,格式如下:
unsigned 整型类型说明符 变量名列表;
例如,一些无符号整型变量的定义代码如下:
01 unsigned int x; /*x为无符号基本整型变量*/ 02 unsigned short int m; /*m为无符号短整型变量*/ 03 unsigned long int m1,m2; /*m1和m2为无符号长整型变量*/ 04 unsigned int a,b,c,d; /*a、b、c、d为无符号基本整型变量*/
上面的代码中的int都可以省略,省略int后的代码如下:
01 unsigned x; /*x为无符号基本整型变量,省略了int*/ 02 unsigned int m; /*m为无符号短整型变量,省略了int*/ 03 unsigned int m1,m2; /*m1和m2为无符号长整型变量,省略了int*/ 04 unsigned a,b,c,d; /*a、b、c、d为无符号基本整型变量,省略了int*/
以上两段代码是等价的。
3.3.2 整型变量占用的字节数与表示范围
在C语言中,数据类型不同,该数据占用的字节数就不同,表示范围也不同。同一类型的数据在不同的编译器中占用的字节数也不同。例如,基本整型变量在Turbo C 3.0开发环境中占用2个字节,而在Visual C++ 6.0开发环境中占用4个字节。各种整型变量在不同的编译器中占用的字节数如表3.4所示。
表3.4 不同的整型变量在Turbo C 3.0和Visual C++ 6.0开发环境中占用的字节数和表示范围
说明
2个字节即16个二进制位,对于带符号整数,它的取值范围是-215~215-1,即-32 768~32 767;对于无符号数,它的取值范围是0~216-1,即0~65 535。4个字节也就是32个二进制位,对于带符号数,它的取值范围是-231~231-1,即-2 147 483 648~2 147 483 647;对于无符号整数,它的取值范围是0~232-1,即0~4 294 967 295。
3.3.3 整型变量的存储形式
无论什么样的类型数据,在计算机中都以二进制形式存储,整型数据也不例外。十进制整型数据65在内存中的存放情况如图3.3所示。
图3.3 十进制数65在内存中的存储示意图
实际上,所有数据是以补码的形式存放的。正数的补码与原码相同,负数的补码是把原码的除符号位外的其他位取反,并在最低位加1。例如,-65在内存中的存放形式如图3.4所示。
图3.4 十进制数-65在内存中的存储示意图
注意
因为整型变量有相应的取值范围,所以它们存放的整数不能超出该变量的取值范围。如果要保存的数超过了该变量的取值范围,那么高位部分将会被舍弃。例如,在Turbo C 3.0开发环境中,如果将一个整数65 536存放在int型变量x中,它在内存中的存放形式如图3.5所示。
图3.5 整数65 536在int型变量x中的存储示意图
因为int型变量只占用2个字节,所以高位的1被舍弃,则它的二进制数是16个0,对应于十进制数0。
3.3.4 整型变量的赋值
在定义了整型变量后,需要使用赋值运算符(即“=”)将数据存放到变量中。赋值操作的一般形式如下:
变量名=整型数据;
它表示将“=”右端的整型数据存放在左端的变量名指示的内存单元中。例如,定义了一个整型变量a并赋值,代码如下:
01 int a; /*定义整型变量a*/ 02 a=29; /*将29赋值给变量a*/
注意
“=”不是等号,而是赋值运算符,它表示将右端的值赋值给左端的变量。
在为变量赋值时,不能超出该变量所表示的范围,否则会产生错误的结果。例如,short int类型的变量的取值范围是-32 768~32 767,以下赋值是错误的:
01 short int b; /*定义短整型变量b*/ 02 b=237 623; /*错误!超过了b的取值范围,实际上b的值是-24 521*/
3.3.5 一个简单的C程序──输出整型变量的值
前面已经讲解了整型变量的定义与赋值,下面来看一个简单的C程序。
图3.6 程序运行结果示意图
【例3-1】输出整型变量a的值。
01 #include<stdio.h> /*包含头文件*/ 02 void main() /*主函数名,必须有*/ 03 { 04 int a; /*定义整型变量a*/ 05 a=20; /*将20赋值给变量a*/ 06 printf("%d\n",a); /*输出整型变量a的值*/ 07 }
程序运行结果如图3.6所示。
这是一个非常简单的C程序。一个C程序必须包含主函数main,即代码的第2行中是必需的,在main之后需要跟一对圆括号。main函数是程序开始执行的地方,前面的void表示函数没有返回值,在该程序中void可以省略。
函数内部使用一对花括号括起来,这称为函数体。任何一个函数体(包括主函数)都由两个部分组成:声明部分和执行部分。声明部分是在程序的编译阶段完成的,执行部分是在程序的执行阶段完成的。
(1)声明部分。声明部分主要是指变量和常量的定义。例如,上面代码的第4行就是声明部分。
(2)执行部分。执行部分主要由除了变量和常量定义之外的语句构成。它是程序的实际起作用的部分。例如,上面的程序的第5~6行都是执行部分。
该程序的第6行是一个输出函数。它的主要作用是输出变量a的值。这个函数分为两个部分:前一部分是控制输出的形式,需要使用双引号括起来;后一部分是要输出的变量值。双引号中的“%d”表示要将变量a以十进制形式输出。“\n”是一个转义字符,表示换行。当输出变量a的值后,应将光标移动到下一行的开始位置,使下一个数据在新的光标位置输出。
使用系统提供的函数printf时,需要在程序的开始添加命令# include<stdio.h>。它是一个宏命令,表示该函数包含在文件stdio.h中。
3.4 实型变量
实型变量只能存放实型(浮点型)数据。实型变量有以下3种类型。
(1)单精度浮点型变量。单精度浮点型变量使用关键字float表示。
(2)双精度浮点型变量。双精度浮点型变量使用关键字double表示。
(3)长双精度浮点型变量。长双精度浮点型变量使用关键字long double表示。
本节主要讲解这3种实型变量的的定义与赋值、表示范围、存储形式。
3.4.1 实型变量的定义与赋值
实型变量的定义的一般形式如下:
实型类型说明符 变量名列表;
实型变量说明符可以是float、double和long double。变量名列表可以是一个变量名,也可以是多个变量名。如果是多个变量名,应使用逗号分隔开。例如,实型变量的定义如下:
01 float f1,f2; /*f1和f2为单精度浮点型变量*/ 02 double average; /*average为双精度浮点型变量*/ 03 long double f; /*f为长双精度浮点型变量*/
与整型变量的赋值一样,可使用赋值运算符“=”将右端的浮点数存放到左端的变量中。既可以将十进制小数赋值给变量,也可以将指数形式的浮点数赋值给变量。例如,实型变量的赋值操作代码如下:
f1=2.35; f2=158.2; f=6.28e5;
在为浮点型变量赋值时,也不可以超过浮点型变量的取值范围,否则也会出现错误的结果。
3.4.2 实型变量的表示范围
各种实型变量在Turbo C 3.0和Visual C++ 6.0开发环境中占用的字节数和表示范围相同。各种实型变量占用的字节数和表示范围如表3.5所示。
表3.5 各种实型变量占用的字节数和表示范围
其中,有效位数是指浮点数最多能精确到小数点后几位。从表3.5可以看出,从float到double再到long double,它们占用的字节数依次增加,表示范围越来越大,有效位数越来越多。表示范围说明了变量的取值范围,有效位反映了它们表示的变量的精度。
3.4.3 一个简单的C程序──输出实型变量的值
【例3-2】一个简单的输出实型变量的值的程序,如下所示。
01 #include<stdio.h> /*包含头文件*/ 02 void main() 03 { 04 float f1; /*定义浮点变量f1*/ 05 f1=2.345; /*为f1赋值*/ 06 printf("%f\n",f1); /*输出变量f1的值*/ 07 }
程序运行结果如图3.7所示。
(1)该程序与例3-1中代码的第1~3行和第7行都是相同的。
图3.7 输出实型变量的值的程序运行结果示意图
(2)第4行是浮点型变量的定义。
(3)第5行是为浮点型变量f1赋值。
(4)第6行是利用函数printf输出变量f1的值。这里的函数printf与例3-1中的函数printf有两处不同:%f和f1。其中,%f表示输出的是浮点型数据,f1是变量名。从运行结果可以看出,在默认情况下,输出的浮点数带有6个小数位。
3.5 字符型变量
字符型变量一般用来存放字符类的数据,且只能存放一个字符。本节主要讲解的内容包括字符型变量的定义与赋值、字符变量的存储形式、字符串数据。
3.5.1 字符型变量的定义与赋值
字符型变量的定义格式如下:
char 字符变量列表;
字符变量的类型只有一种,使用关键字char表示。例如,定义2个字符的代码如下:
char c1,c2;
c1和c2都被定义为字符类型。它们可以各存放一个字符。接下来就可以为字符赋值了,代码如下:
01 c1='A'; 02 c2='B'
需要注意,字符型数据需要使用一对单引号括起来。在所有的编译器中,一个字符型变量占用一个字节。
3.5.2 字符型数据的存储形式
字符型数据在内存中也是以二进制形式存放的。实际上,每一个字符都有唯一的一个ASCII码与之对应,ASCII码就是一个整数。整数当然是以二进制形式存放的,因此,字符型数据也是以二进制形式存放的。例如,字符'A'的ASCII码是65,字符'B'的ASCII码是66,字符'a'的ASCII码是97,字符'b'的ASCII码是98。字符与ASCII码之间的对应关系可以通过字符与ASCII码对照表查到。
字符'A'在内存中的存储形式如图3.8所示。
在C语言中,字符型数据与整型数据是通用的。可以将一个整型数据赋值给字符型变量,也可以将一个字符型数据赋值给整型变量。一个字符型数据可以整数形式输出,一个整型数据也可以字符形式输出。
图3.8 字符'A'在内存中的存储示意图
1.以字符形式和整数形式输出字符型变量的值
【例3-3】输出字符型变量中的值。
01 #include<stdio.h> /*包含头文件*/ 02 void main() 03 { 04 char c1,c2; /*定义两个字符型变量c1和c2*/ 05 c1='a'; /*为c1赋值*/ 06 c2='b'; /*为c2赋值*/ 07 printf("%c,%c\n",c1,c2); /*以字符形式输出c1和c2的值*/ 08 printf("%d,%d\n",c1,c2); /*以整数形式输出c1和c2的值*/ 09 }
程序运行结果如图3.9所示。
图3.9 输出字符型变量的值的程序运行结果示意图
(1)第7行是以字符形式输出c1和c2的值。两个%c表示以字符形式分别输出c1和c2的值,双引号中的逗号按照原样输出。
(2)第8行是以整数形式输出c1和c2的值。这种以整数形式的输出方式实际上输出的是c1和c2的ASCII码。
2.以整数形式和字符形式输出整型变量的值
【例3-4】输出整型变量中的值。
01 #include<stdio.h> /*包含头文件*/ 02 void main() 03 { 04 int x,y; /*定义变量x和y*/ 05 x=97; /*为变量x赋值*/ 06 y=98; /*为变量y赋值*/ 07 printf("%d,%d\n",x,y); /*以整数形式输出x和y的值*/ 08 printf("%c,%c\n",x,y); /*以字符形式输出x和y的值*/ 09 }
程序运行结果如图3.10所示。
(1)第7行是以整数形式输出x和y的值,即输出97和98。
(2行是以字符形式输出x和y的值。因为97和98分别是字符'A'和'B'的ASCII码,所以以%c的形式输出时,会输出'A'和'B'。
从以上两个例子可以看出,字符数据和字符数据在C语言中是通用的,但是整数数据和字符数据在内存中占用的字节并不相同。如果将一个字符型数据赋值给整型变量,就是将该字符的ASCII码存放在整型变量的低位字节中。例如,将字符'A'赋值给整型变量a,代码如下:
图3.10 以整数形式和字符形式输出整型变量的值示意图
01 int a; /*定义整型变量a*/ 02 a='A'; /*将字符'A'赋值给a*/
字符'A'在变量a中的存储形式如图3.11所示。
图3.11 字符'A'在变量a中的存储示意图
在将整型数据以字符形式输出时,只取低位字节的数据作为ASCII码输出。相反,如果将一个整型数据存放在字符变量中,如果整型数据超出字符变量的取值范围,则高位部分将被舍弃。
3.5.3 字符数据与字符串数据的区别
字符串可以看成是由多个字符构成的数据。字符数据与字符串数据的主要区别体现在以下几个方面。
(1)字符使用单引号括起来,字符串使用双引号括起来。例如,'A'、'a'是字符数据,"electrical"和"pbulish"是字符串数据。
(2)字符数据只有一个字符,字符串数据可以包括零个、一个或多个字符。例如,'B'、'c'是正确的,而"是错误的,即单引号内不能没有字符。'a'和'A'是字符数据,"a"和"A"是字符串数据。
(3)可以将一个字符数据赋值给字符变量,但不可以将一个字符串数据赋值给字符变量。例如,如果定义了字符变量,则代码如下:
01 char c; /*定义一个字符型变量*/ 02 c='X'; /*正确!将字符'X'赋值给变量c*/ 03 c="a" /*错误!不能将字符串"a"赋值给变量c*/ 04 c="pku"; /*错误!不能敬爱那个字符串数据"pku"赋值给变量c*/
(4)在C语言中,字符串的末尾都自动被添加一个'\0'作为字符串的结束标志。例如,字符串数据"northwest"的存储形式如图3.12所示。
图3.12 字符串"northwest"的存储示意图
字符串"northwest"在内存中实际占有了10个字节,而不是9个字节。但在输出该字符串时,并不输出最后的'\0',它仅仅是一个字符串结束的标志。
注意
在C语言中,并没有专门的字符串变量,字符串的存储与操作将在数组部分和指针部分具体进行讲解。
3.6 小结
本章主要讲解了C语言中的几种基本数据类型──整型、实型和字符型。本章首先介绍了C语言中数据类型的分类,然后介绍了变量和常量。变量就是可以改变的量,主要用来存放经常发生变化的数据。常量就是在程序运行期间不能改变的量,主要存放不变的数据。本章接着分别讲解了整型变量、实型变量和字符型变量的定义、占用字节数和表示范围、存储形式,并分别通过一个简单的实例讲解了变量的用法。本章的重点是变量的定义和输出。通过本章的学习,希望大家能够学会编写最简单的C程序。