很少有程序会像2.1节中的示例那样简单。大多数程序在产生输出之前往往需要执行一系列的计算,因此需要在程序执行过程中有一种临时存储数据的方法。和大多数编程语言一样,C语言中的这类存储单元被称为 变量 (variable)。
每一个变量都必须有一个
类型
(type)。类型用来说明变量所存储的数据的种类。C语言拥有广泛多样的类型。但是现在,我们将只限定在两种类型范围内:
int
类型和
float
类型。因为类型会影响变量的存储方式以及允许对变量进行的操作,所以选择合适的类型是非常关键的。数值型变量的类型决定了变量所能存储的最大值和最小值,同时也决定了是否允许在小数点后出现数字。
int
(integer的简写)型变量可以存储整数,如0、1、392或-2553。但是,整数的取值范围(➤7.1节)是受限制的。最大的整数通常是2 147 483 647,但在某些计算机上也可能是32 767。
float
(即floating-point的简写)型变量可以存储比
int
型变量大得多的数值。而且,
float
型变量可以存储带小数位的数,如379.125。但
float
型变量也有一些缺陷。进行算术运算时
float
型变量通常比
int
型变量慢;更重要的是,
float
型变量所存储的数值往往只是实际数值的一个近似值。如果在一个
float
型变量中存储0.1,以后可能会发现变量的值为0.099 999 999 999 999 87,这是舍入造成的误差。
在使用变量之前必须对其进行
声明
(为编译器所做的描述)。为了声明变量,首先要指定变量的
类型
,然后说明变量的
名字
。(程序员决定变量的名字,命名规则见2.7节。)例如,我们可能这样声明变量
height
和
profit
:
int height;
float profit;
第一条声明说明
height
是一个
int
型变量,这也就意味着变量
height
可以存储一个整数值。第二条声明则表示
profit
是一个
float
型变量。
如果几个变量具有相同的类型,就可以把它们的声明合并:
int height, length, width, volume;
float profit, loss;
注意每一条完整的声明都要以分号结尾。
在
main
函数的第一个模板中并没有包含声明。当
main
函数包含声明时,必须把声明放置在语句之前:
int main(void) { 声明 语句 }
第9章中我们会看到,函数和程序块(包含嵌入声明的语句,➤10.3节)一般都有这样的要求。就书写格式而言,建议在声明和语句之间留出一个空行。
在C99中,声明可以不在语句之前。例如,
main
函数中可以先有一个声明,后面跟一条语句,然后再跟一个声明。为了与以前的编译器兼容,本书中的程序不会采用这一规则。
变量通过 赋值 (assignment)的方式获得值。例如,语句
height = 8;
length = 12;
width = 10;
把数值
8
、
12
和
10
分别赋给变量
height
、
length
和
width
,
8
、
12
和
10
称为
常量
(constant)。
变量在赋值或以其他方式使用之前必须先声明。也就是说,我们可以这样写:
int height;
height = 8;
但下面这样是不行的:
height = 8; /*** WRONG ***/
int height;
赋给
float
型变量的常量通常带小数点。例如,如果
profit
是一个
float
型的变量,可能会这样对其赋值:
profit = 2150.48;
当我们把一个包含小数点的常量赋值给
float
型变量时,最好在该常量后面加一个字母
f
(代表
float
):
profit = 2150.48f;
不加
f
可能会触发编译器的警告。
正常情况下,要将
int
型的值赋给
int
型的变量,将
float
型的值赋给
float
型的变量。混合类型赋值(例如把
int
型的值赋给
float
型变量,或者把
float
型的值赋给
int
型变量)是可以的,但不一定安全,参见4.2节。
变量一旦被赋值,就可以用它来辅助计算其他变量的值:
height = 8;
length = 12;
width = 10;
volume = height * length * width; /* volume is now 960 */
在C语言中,符号
*
表示乘法运算,因此上述语句把存储在
height
、
length
和
width
这3个变量中的数值相乘,然后把运算结果赋值给变量
volume
。通常情况下,赋值运算的右侧可以是一个含有常量、变量和运算符的公式(在C语言的术语中称为
表达式
)。
用
printf
可以显示出变量的当前值。以
Height: h
为例,这里的
h
表示变量
height
的当前值。我们可以通过如下的
printf
调用来实现输出上述信息的要求:
printf("Height: %d\n", height);
占位符
%d
用来指明在显示过程中变量
height
的值的显示位置。注意,因为在
%d
后面放置了
\n
,所以printf在显示完
height
的值后会跳到下一行。
%d
仅用于
int
型变量。如果要显示
float
型变量,则要用
%f
来代替
%d
。默认情况下,
%f
会显示出小数点后6位数字。如果要强制
%f
显示小数点后
p
位数字,可以把
.p
放置在
%
和
f
之间。例如,为了显示信息
Profit: $2150.48
可以把
printf
写为如下形式:
printf("Profit: $%.2f\n", profit);
C语言没有限制调用一次
printf
可以显示的变量数量。为了同时显示变量
height
和变量
length
的值,可以使用下面的
printf
调用语句:
printf("Height: %d Length: %d\n", height, length);
程序 计算箱子的空间重量
运输公司特别不喜欢又大又轻的箱子,因为箱子在卡车或飞机上运输时要占据宝贵的空间。事实上,对于这类箱子,运输公司常常要求按照箱子的体积而不是重量来支付额外的费用。在美国,通常的做法是把体积除以166(这是每磅允许的立方英寸 数)。如果除得的商(也就是箱子的“空间”重量或“体积”重量)大于箱子的实际重量,那么运费就按照空间重量来计算。(除数166是针对国际运输的,计算美国国内运输的空间重量时通常用194代替。)
假设运输公司雇你来编写一个计算箱子空间重量的程序。因为刚刚开始学习C语言,所以你决定先编写一个计算特定箱子空间重量的程序来试试身手,其中箱子的长、宽、高分别是12英寸、10英寸和8英寸。C语言中除法运算用符号
/
表示。所以,显然计算箱子空间重量的公式如下:
weight = volume / 166;
这里的
weight
和
volume
都是整型变量,分别用来表示箱子的重量和体积。但是上面这个公式并不是我们所需要的。在C语言中,如果两个整数相除,那么结果会被“截短”:小数点后的所有数字都会丢失。12英寸×10英寸×8英寸的箱子体积是960立方英寸,960除以166的结果是5而不是5.783,这样使得重量
向下
舍入,运输公司则希望结果
向上
舍入。一种解决方案是在除以166之前把体积数加上165:
weight = (volume + 165) / 166;
这样,体积为166立方英寸的箱子的空间重量就为331/166,舍入为1;而体积为167立方英寸的箱子的空间重量则为332/166,舍入为2。下面给出了利用这种方法编写的计算空间重量的程序。
dweight.c
/* Computes the dimensional weight of a 12" x 10" x 8" box */
#include <stdio.h>
int main(void)
{
int height, length, width, volume, weight;
height = 8;
length = 12;
width = 10;
volume = height * length * width;
weight = (volume + 165) / 166;
printf("Dimensions: %dx%dx%d\n", length, width, height);
printf("Volume (cubic inches): %d\n", volume);
printf("Dimensional weight (pounds): %d\n", weight);
return 0;
}
这段程序的输出结果是
Dimensions: 12x10x8
Volume (cubic inches): 960
Dimensional weight (pounds): 6
当程序开始执行时,某些变量会被自动设置为零,而大多数变量则不会(➤18.5节)。没有默认值并且尚未在程序中被赋值的变量是 未初始化的 (uninitialized)。
如果试图访问未初始化的变量(例如,用
printf
显示变量的值,或者在表达式中使用该变量),可能会得到不可预知的结果,如2568、-30 891或者其他同样没有意义的数值。在某些编译器中,可能会发生更坏的情况(甚至是程序崩溃)。
我们当然可以总是采用赋值的方法给变量赋初始值,但还有更简便的方法:在变量声明中加入初始值。例如,可以在一步操作中声明变量
height
并同时将其初始化:
int height = 8;
按照C语言的术语,数值
8
是一个
初始化器
(initializer)。
在同一个声明中可以对任意数量的变量进行初始化:
int height = 8, length = 12, width = 10;
注意,上述每个变量都有属于自己的初始化器。在接下来的例子中,只有变量
width
拥有初始化器
10
,而变量
height
和变量
length
都没有(也就是说这两个变量仍然未初始化):
int height, length, width = 10;
printf
的功能不局限于显示变量中存储的数,它可以显示
任意
数值表达式的值。利用这一特性既可以简化程序,又可以减少变量的数量。例如,语句
volume = height * length * width;
printf("%d\n", volume);
可以用以下形式代替:
printf("%d\n", height * length * width);
printf
显示表达式的值的能力说明了C语言的一个通用原则:
在任何需要数值的地方,都可以使用具有相同类型的表达式
。