2.3 变量及变量的应用
变量是在程序运行中数据可以发生变化的量。从计算机内部来看,变量是内存中一块存储空间。变量的基本形式是简单变量,即有基本数据类型声明的变量,主要包括整型变量、实型变量、字符型变量。本节主要介绍各种简单变量,应注意的是简单变量不是一个简单的数据,在学习中更应注意其存储的特点。
2.3.1 整型变量
整型是常用的一种数据类型。程序中声明一个整型变量,在编译时系统根据具体的类型,分配一定大小的空间来存放所需的数据。但是不同的操作系统,或者不同的C语言编译器为整型分配的空间是不同的。本节将讨论整型变量类型、整型数据的存储及整型变量的使用。
1.整型数据在内存中的存放形式
在计算机中任何信息都是以二进制的形式存储的,二进制数每一位是0或1,8个二进制位组成一个字节(byte),两个字节组成一个字(word)。整数能存储的最大值是由计算机给它分配的存储空间的大小决定的,而整数所占的存储空间因不同的计算机而有所不同。例如,某种计算机可能用16位(两个字节)来存储一个整数,而另一种计算机则可能用32位(四个字节)来存储。在Turbo C系统中,普通整型用2个字节来存放。
当一个整数存储在计算机中时,左起第一位叫做第0位,即符号位,它用来表示该数是正数或负数。如果是负数,符号位被置1,正数则为0。两个字节能表示的整数范围是-32768~32767。
一般情况下内存中的数值是以补码表示的。有关补码读者不需了解过多,只需知道下面两点:
◆ 正数的补码和原码相同。
◆ 负数的补码将该数的绝对值的二进制形式按位取反再加1。
2.整型变量的分类
用计算机解决不同的问题,对数据的具体要求也不一样。由整型变量在内存中分配的内存不同,主要有以下几种整数类型:
◆ 基本型:类型说明符为int,在内存中占2个字节。
◆ 短整量:类型说明符为short int或short。所占字节和取值范围均与基本型相同。
◆ 长整型:类型说明符为Iong int或Iong,在内存中占4个字节。
◆ 无符号型:类型说明符为unsigned。
无符号型又可与以下三种类型匹配而构成:
◆ 无符号基本型:类型说明符为unsigned int或unsigned。
◆ 无符号短整型:类型说明符为unsigned short。
◆ 无符号长整型:类型说明符为unsigned Iong。
各种无符号类型量所占的内存空间字节数与相应的有符号类型量相同。但由于省去了符号位,所以不用表示负数,符号位也表示数值。有符号整型变量由于最高位用来表示符号,最大只能表示32 767;而无符号整型变量最高位也用来表示数据,所以它能表示的最大值是65 535。表2.3列举了Turbo C中各类整型量所分配的内存字节数及数的表示范围。
表2.3 整数类型
3.整型变量的定义
变量在使用前必须定义,定义的目的是通知编译系统变量的类型和变量名。
变量定义的一般形式为:
类型说明符 变量名标识符, 变量名标识符, ...;
例如下面的几个例子:
int a,b,c; /*a,b,c为整型变量*/ long x,y; /*x,y为长整型变量*/ unsigned p,q; /*p,q为无符号整型变量*/
说明
其中类型说明符可为任意系统认可的数据类型。变量名必须以标识符命名。以下的变量定义与整型的变量定义相同,不再做特殊说明。
在进行变量定义时,应注意以下几点:
◆ 允许在一个类型说明符后,定义多个相同类型的变量。各变量名之间用逗号分隔。类型说明符与变量名之间至少用一个空格分隔。
◆ 最后一个变量名之后必须以分号“;”结尾。
◆ 变量定义必须放在变量使用之前。一般放在函数体的开头部分。
代码2.9说明了整型变量的定义与使用。
代码2.9 整型变量的定义与使用:fiIe9.c
#include "stdio.h" main() { long x,y; int a,b,d; unsigned int c; /*定义整型变量*/ x=-5,y=6; /*整型变量赋初值*/ a=3,b=8; c=x+a; d=y+b; /*整型变量之间的赋值与运算*/ printf("c=x+a=%u,d=y+b=%d\n",c,d); /*输出无符号数c和整型d的值*/ }
程序运行的结果为:
c=x+a=65534,d=y+b=14
从程序中可以看到,x,y是长整型变量,a,b,d是基本整型变量,c为无符号型变量。它们之间允许进行运算,运算结果的类型与变量定义时的数据类型一致。本例说明,不同类型的整型量可以参与运算并相互赋值。其中的类型转换是由编译系统自动完成的。有关类型转换的规则将在以后介绍。
4.整型数据的赋值
可以将一个整型常量或整型变量赋值给整型变量,例如:
int a=100;
但是要注意,任何一个整型变量占用一定的存储空间,因此其存储的数据取值范围也就是一定的,详细情况见表2.3。例如将一个大于32 767或小于-32 768的数据赋值给一个int型变量就会产生溢出,代码2.10说明了整型数据溢出时的情况。
代码2.10 整型数据的溢出:fiIe10.c
#include "stdio.h" main() { int a,b; a=32767; /*整型变量赋值界限*/ b=a+1; /*溢出*/ printf("%d,%d\n",a,b); }
整型数据的溢出在编译时不会出错,但在程序运行中会出现错误,因此应该避免。平时应注意不同类型数据的取值范围,如果整型变量不能处理问题,则可以考虑用长整型变量。可以将一个整型常量后面加一个字母I或L,则认为此常量为长整型常量,也可以将此长整型常量赋值给一个长整型变量。例如:
long l=1000L;
2.3.2 实型变量
实型也称为浮点型,是数值计算问题中所需的重要类型。本节将讨论实型变量类型、实型数据的存储及实型变量的使用。
1.实型数据在内存中的存放形式
与整型数据的存储形式不同,实型数据是以指数形式存放的。一般情况下,系统将一个实型数据分为小数部分和指数部分并分别存放。指数部分采用规范化的指数形式,具体存放结构如图2.5所示。实型数据一般占4个字节(32位)内存空间。按指数形式存储。实数2.71828在内存中的存放形式如图2.5所示。
图2.5 实型数据的存放
不同的C语言系统对于基数和指数部分所占位数的定义是不同的。其中小数部分占的位(bit)数越多,数的有效数字越多,精度越高;指数部分占的位数越多,则能表示的数值范围越大。
2.实型变量的分类
按照实型变量可表示的精度,实型变量分为:单精度(fIoat型)、双精度(doubIe型)和长双精度(Iong doubIe型)三类。
在Turbo C中单精度型占4个字节(32位)内存空间,只能提供7位有效位数。双精度型占8个字节(64位)内存空间,可提供16位有效位数。表2.4列出了在Turbo C中各种实型数据所分配的内存和有效位数。
表2.4 实型常量分类
实型变量定义的格式和书写规则与整型相同,例如下面两条定义语句:
float x,y; /*x,y为单精度实型量*/ double d1,d2; /*d1,d2为双精度实型量*/
3.实型变量的赋值
可以将实型常量或实型变量赋值给实型变量。注意单精度实型数据的有效位数是6~7位,在进行赋值和计算时会产生误差,在双精度实型数据和长双精度实型数据中也同样存在此问题。代码2.11将一个有效数字位超过7位的数赋值给实型变量,然后输出实型变量的值,说明实型数据的确存在误差。
代码2.11 实型数据的输出误差:fiIe11.c
#include "stdio.h" main() { float f=123456789; /*单精度变量赋初值*/ double d=123456789; printf("\nf=%f\td=%f",x,y); }
程序运行的结果为:
x=123456792.000000 y=123456789.000000
从运行结果可以看出,单精度实型变量f只接收了前面7位,从第8位开始数据不准确,所以在使用实型数据时一定注意可能产生的误差。应该避免将一个很大的数和一个很小的数直接进行运算,否则这个很小的数不会参加运算。代码2.12说明实型数据运算时将忽略特别小的数的值。
代码2.12 实型数据的运算:fiIe12.c
#include "stdio.h" main() {float a,b; a=1.234e-8; /*指数型常量赋初值*/ b=a+20; /*错误算术运算*/ printf("%f\n",a); printf("%f\n",b); }
程序运行的结果为:
0.000000 20.000000
说明
Turbo C中两个实型数据的运算无法判断结果是不是0,任何足够小的数都可以被认为是0。同时规定小数后最多保留6位,其余部分四舍五入。
2.3.3 字符型变量
字符型变量用来存放字符,字符变量的类型说明符是char。注意一个字符变量只能放一个字符,不要以为在一个字符变量中可以放一个字符串。这一小节介绍字符型变量的定义、存储及用法。
每个字符变量仅占用一个字节,存放该字符的编码。该编码是一个数字,并依赖于所使用的编码系统(即与机器相关)。最普通的编码是ASCII(American Standard Code for Information Interchange),即美国信息交换标准编码。例如字符A的ASCII码为65,字符a的ASCII码为97。
1.字符数据在内存中的存储形式
将一个字符常量放在一个字符变量中,实际上并不是将字符的点阵信息或矢量信息放在内存中,而是将该字符的ASCII码信息放在相应的内存中。例如字符“a”的ASCII码为97,字符“b”的ASCII码为98,如果将其分别放在字符变量c1和c2中,实际上是以二进制的形式存储的(参见图2.7),所以也可以把它们看成是整型量。
图2.7 字符变量的存储
2.字符变量的定义
字符变量的定义形式如下:
char 字符变量名1, 字符变量名2, 字符变量名3, …;
例如下面定义了两个字符变量c1,c2:
char c1,c2; /*定义字符型的变量*/
3.字符变量的赋值
C语言允许对整型变量赋以字符值,也允许对字符变量赋以整型值。可以将一个字符常量或字符变量赋值给一个字符变量,也可以将0~255的整型数据赋值给一个字符变量,并且字符变量、字符常量、0~255的整型数据之间可以进行运算。在输出时,允许把字符变量按整型量输出,也允许把整型量按字符量输出。整型量为二字节量,字符量为单字节量,当整型量按字符型量处理时,只有低8位字节参与处理。代码2.13说明可以向字符变量赋以整数。
代码2.13 向字符变量赋以整数:fiIe13.c
#include "stdio.h" main() { char c1,c2; c1=97; /* 将97赋给c1 */ c2='b'; /* 将98赋给c2 */ printf("%c,%c\n",c1,c2); /* 输出c1,c2存放的字符 */ printf("%d,%d\n",c1,c2); /* 输出c1,c2中存放的数据 */ }
程序运行的结果为:
a,b 97,98
本程序中定义c1、c2为字符型,但在赋值语句中赋以整型值。从结果看c1、c2值的输出形式取决于printf函数格式串中的格式符,当格式符为"c"时,对应输出的变量值为字符,当格式符为"d"时,对应输出的变量值为整数。
小写字母a和b的ASCII码分别为97和98,大写字母A和B的ASCII码为65和66,可以看出,小写字母的ASCII码比其大写字母大32,即'a'-32就得到'A',计算非常方便。代码2.14说明了字符型数据可以与整数进行运算。
代码2.14 小写字母转换成大写字母:fiIe14.c
main() { char c1,c2; a='a'; b='b'; a=a-32; /* 将小写字母减32得到大写字母 */ b=b-32; printf("%c,%c\n%d,%d\n",a,b,a,b); }
屏幕显示:
A,B 66,65
2.3.4 变量的使用规范
C语言中对变量的使用比较灵活,一旦使用不当会给程序带来不可预知的后果。因此在使用中要满足以下几个方面的要求。
(1)使用一个变量之前,必须先定义。变量定义的一般格式如下:
数据类型 变量名1[= 初始值1], 变量名2[= 初始值2], ...;
(2)每一个变量有一个具体的类型,同时每一个变量有一个名字,其命名规则与标识符相同。为了提高程序的可读性,给变量命名时,应该注意使用有意义的名字,以帮助描述变量所保存的值。最好是一开始就坚持使用小写字母。
(3)每一个变量保存一个值。如果需要变量保存某一个值,就把该值赋给变量。在程序设计中,变量获得值的方法有以下三种:
◆ 定义变量的同时对变量进行赋值,称为变量的初始化。例如:
int a=5; float p=3.14; char c1='a';
也可以对被定义的变量的一部分赋初值。例如:
int a,b,c=10;
如果对几个变量赋予同一个值,则可以写成:
int a=10,b=10,c=10;
不可写成
int a=b=c=10;
◆ 在程序运行时进行赋值。例如:
int a,b; a=3; b=4;
如果对几个变量赋予同一个值,则可以写成:
int x,y,z; x=y=z=10; /*变量赋相同初值的书写形式*/
变量的初始化不是在编译阶段完成的,而是在程序运行时执行本函数时赋以初值的,所以初始化语句:
int a=10;
相当于下面的:
int a; a=10;
◆ 利用函数scanf从键盘上输入值,例如:
double d1,d2; scanf("%f%f",&d1,&d2);
具体函数使用形式在后面的章节描述。
代码2.15是一种整型和实型变量的综合应用,计算一周的工资。
代码2.15 变量的应用:fiIe15.c
#include <stdio.h> main() { int workDays = 5; float workHours,payRate,weeklyPay; workHours = 7.5; /*使用前变量赋初值*/ payRate = 38.55; weeklyPay = workDays * workHours * payRate; /*整型变量和实型变量共同运算*/ printf("Weekly Pay = %f\n",weeklyPay); /*注意输出格式*/ }
程序运行的结果为:
Weekly Pay = 1445.625000
注意
如果定义一个变量时,没有给它赋初值,那么它的值是不定的。
2.3.5 变量常见错误分析方法
变量是程序中使用最多的数据,它可以保存程序中处理的数据。由于其使用灵活,在使用中常常出现一些错误。代码2.16是一个变量名拼写错和没声明变量的例子。
代码2.16 变量名拼写错和没声明变量:fiIe16.c
#include "stdio.h" main() { char student; float score; num=11015; /*非法变量*/ student='a'; score=80; printf("the num %ld the student %c\'s score %f",num,stadent,score);/*错误代码*/ }
编译时的错误提示:
Undefined symbol 'num' in function main Undefined symbol 'stadent' in function main
出错的原因是变量num没有先定义而使用,而变量student有定义但使用时误写为stadent,也相当于变量没有定义,编译时会出错。只需把变量num定义,改写输出时变量stadent的名字为student即可解决这些错误。代码2.17是一个变量在使用前未赋初值的例子。
代码2.17 变量在使用前无初值:fiIe17.c
#include "stdio.h" main() { int num; printf("%d \n",num); /*没有赋初值*/ }
编译时的提示信息是:
Possible use of 'num' before definition in function main
这样使用变量,编译系统只给出警告错误提示。因为变量中不是没有数据,只是数据的值是随机的,这样使用在复杂的程序中可能会产生莫名的错误。所以在使用中一定要注意,变量使用前要赋初值。