现在读者一定很渴望编写程序,让计算机与外界进行实际的交互。我们不希望程序只能做打字员的工作,显示包含在程序代码中的固定信息。的确,编程的内涵远不止此。理想情况下,我们应能从键盘上输入数据,让程序把它们存储在某个地方,这会让程序更具多样性。程序可以访问和处理这些数据,而且每次执行时,都可以处理不同的数据值。每次运行程序时输入不同的信息正是整个编程业的关键。在程序中存储数据项的地方是可以变化的,所以叫做变量(variable),而这正是本章的主题。
本章的主要内容:
● 内存的用法及变量的概念
● 在C中如何计算
● 变量的不同类型及其用途
● 强制类型转换的概念及其使用场合
● 编写一个程序,计算树木的高度
首先看看计算机如何存储程序要处理的数据。为此,就要了解计算机的内存,在开始编写第一个程序之前,先简要介绍计算机的内存。
计算机执行程序时,组成程序的指令和程序所操作的数据都必须存储到某个地方。这个地方就是机器的内存,也称为主内存(main memory),或随机访问存储器(Random Access Memory,RAM)。RAM是易失性存储器。关闭PC后,RAM的内容就会丢失。PC把一个或多个磁盘驱动器作为其永久存储器。要在程序结束执行后存储起来的任何数据,都应打印出来或写入磁盘,因为程序结束时,存储在RAM中的结果就会丢失。
可以将计算机的RAM想象成一排井然有序的盒子。每个盒子都有两个状态:满为l,空为0。因此每个盒子代表—个二进制数:0或1。计算机有时用真(true)和假(false)表示它们:1是真,0是假。每个盒子称为—个位(bit),即二进制数(binary digit)的缩写。
注意:
如果读者不记得或从来没学过二进制数,可参阅附录A。但如果不明白这些内容,不用担心,因为这里的重点是计算机只能处理0与1,而不能直接处理十进制数。程序使用的所有数据(包括程序指令)都是由二进制数组成的。
为了方便起见,内存中的位以8个为—组,每组的8位称为一个字节(byte)。为了使用字节的内容,每个字节用一个数字表示,第—个字节用0表示,第二个字节用1表示,直到计算机内存的最后—个字节。字节的这个标记称为字节的地址(address)。因此,每个字节的地址都是唯一的。每栋房子都有一个唯一的街道地址。同样,字节的地址唯—地表示计算机内存中的字节。
总之,内存的最小单位是位(bit),将8个位组合为一组,称为字节(byte)。每个字节都有唯一的地址。字节地址从0开始。位只能是0或1,如图2-1所示。
图2-1 内存中的字节
计算机内存的常用单位是千字节(KB)、兆字节(MB)、千兆字节 (GB)。大型磁盘驱动器使用兆兆字节(TB)。这些单位的意义如下:
● 1KB是1 024字节。
● 1MB是1 024KB,也就是1 048 576字节。
● 1GB是1 024MB,也就是1 073 741 841字节。
● 1TB是1 024GB,也就是1 099 511 627 776字节。
如果PC有1GB的RAM,字节地址就是0~1 073 741 841。为什么不使用更简单的整数,例如千、百万或亿?因为从0到1023共1024个数字,而在二进制中,1023的10个位刚好全是l:11 1111 1111,它是一个非常方便的二进制数。1000是很好用的十进制数,但是在二进制的计算机里就不再那么方便了,它是111110 1000。因此以KB(1 024字节)为单位,是为了方便计算机使用。同样,MB需要20个位,GB需要30个位。
但是硬盘的容量可能出现混乱。磁盘制造商常常宣称他们生产的磁盘的容量是256GB或1TB,而实际上这两个数字表示2560亿字节及1万亿字节。当然,2560亿字节只有231MB,而1万亿字节只有911GB,所以磁盘制造商给出的硬盘容量有误导作用。
有了字节的概念,下面看看如何在程序里使用这些内存。
变量是计算机里一块特定的内存,它是由一个或多个连续的字节所组成,一般是1、2、4、8或16字节。每个变量都有一个名称,可以用该名称表示内存的这个位置,以提取它包含的数据或存储一个新数值。
下面编写一个程序,用第1章介绍的printf()函数显示你的薪水。假设你的薪水是10 000元/月,则很容易编写这个程序。
// Program 2.1 What is a Variable?
#include <stdio.h>
int main(void)
{
printf("My salary is $10000");
return 0;
}
这个程序的工作方式不需要多做解释,它和第一章开发的程序差不多。如何修改这个程序,让它能够根据存储在内存中的值,定制要显示的信息?这有几种方法,它们有一个共同点:使用变量。
在这个例子里,可以分配一块名为salary的内存,把值10 000存储在该变量中。要显示薪水时,可以使用给变量指定的名称salary,将存储在其中的值10 000显示出来。程序用到变量名时,计算机就会访问存储在其中的值。变量的使用次数是不受限制的。当薪水改变时,只要改变salary变量存储的值,整个程序就会使用新的值。当然,在计算机中,所有的值都存储为二进制数。
程序中变量的数量是没有限制的。在程序执行过程中,每个变量包含的值由程序的指令来决定。变量的值不是固定的,而可以随时改变,且没有次数的限制。
注意:
变量可以有一个或多个字节,那么,计算机如何知道变量有多少个字节?下一节会提到,每个变量都有类型来指定变量可以存储的数据种类。变量的类型决定了为它分配多少个字节。
给变量指定的名称一般称为变量名。变量的命名是很有弹性的。它可以是一个或多个大写或小写字母、数字和下划线( _ )(有时下划线也算作字母),但要以字母开头。下面是一些正确的变量名:
Radius diameter Auntie_May Knotted_Wool D678
变量名不能以数字开头,所以8_Ball和6_pack都是不合法的名称。变量名只能包含字母、下划线和数字,所以Hash!及Mary-Lou都不能用作变量名。Mary-Lou是一个常见的错误,但是Mary_Lou就是可以接受的。变量名中不能有空格,所以Mary Lou会被视为两个变量名Mary和Lou。以一或两个下划线开头的变量名常用在头文件中,所以在给变量命名时,不要将下划线用作第一个字符,以免和标准库里的变量名冲突。例如最好避免使用_this和_that这样的变量名。变量名的另一个要点是,变量名是区分大小写的,因此Democrat和democrat是不同的。
可以在上述限制内随意指定变量名,但最好使变量名有助于了解该变量包含的内容,例如用变量名x来存储薪水信息就不好,而使用变量名salary就好得多,对其用途不会有什么疑义。
警告:
变量名可以包含的字符数取决于编译器,遵循C语言标准的编译器至少支持31个字符,只要不超过这个长度就没问题。建议变量名不要超过这个长度,因为这样的变量名比较繁琐,代码也难以理解。有些编译器会截短过长的变量名。
变量有几种不同的类型,每种变量都用于存储特定类型的数据。有几种变量可存储整数、非整数的数值和字符。一些类型存储特定的数据(例如整数),它们之间的区别是它们占用的内存量和可以存储的数值范围。首先看看用于存储整数的变量。
整数是没有小数点的数字。下面是一个例子:
123 10,999,000,000 20,000 88 1
这些数值是整数,但这对程序而言并不完全正确。整数是不能包含逗号的,所以第二个值在程序里应该写成10999000000,第三个值应写成20000。
下面是一些不是整数的例子:
1.234 999.9 2.0 –0.0005 3.14159265
2.0一般算作整数,但是计算机不将它算作整数,因为它带有小数点。在程序里,必须把这个数字写作2,不带小数点。在C程序中,整数总是写成不带小数点的数字,如果数字中有小数点,就不是整数,而是浮点数,详见后面的内容。在详细讨论整型变量之前,先看看程序里一个简单的变量,学习变量的用法。
试试看:使用变量
回到输出薪水的例子。将前面的程序改为使用一个int型变量:
// Program 2.2 Using a variable
#include <stdio.h>
int main(void)
{
int salary; //Declare a variable called salary
salary = 10000; //Store 10000 in salary
printf("My salary is %d.\n", salary);
return 0;
}
输入这个例子,编译、链接并执行,会得到下面的结果:
My salary is 10000.
代码的说明
前三行和前一个例子相同,下面看看新的语句。用来存放薪水的变量声明语句如下:
intsalary; //Declare a variable called salary
这个语句称为变量声明,因为它声明了变量的名称。在这个程序中,变量名是salary。
警告:
变量声明语句以分号结束。如果漏掉分号,程序编译时会产生错误。
变量声明也指定了这个变量存储的数据类型,这里使用关键字int指定,salary用来存放一个整数。关键字int放在变量名称之前。这是可用于存储整数的几个类型之一。
如后面所述,声明存储其他数据类型的变量时,要使用另一个关键字指定数据类型,其方式大致相同。
注意:
关键字是特殊的C保留字,对编译器有特殊的意义。不能将它们用作变量名称或代码中的其他实体,否则编译器会生成错误消息。
变量声明也称为变量的定义,因为它分配了一些存储空间,来存储整数值,该整数可以用变量名salary来引用。
注意:
声明引入了一个变量名,定义则给变量分配存储空间。有这个区别的原因在本书后面会很清楚。
当然,现在还未指定变量salary的值,所以此刻该变量包含一个垃圾值,即上次使用这块内存空间时遗留在此的值。
下一个语句是:
salary= 10000; //Store 10000 in salary
这是一个简单的算术赋值语句,它将等号右边的数值存储到等号左边的变量中。这里声明了变量salary,它的值是10 000。将右边的值10 000存储到左边的变量salary中。等号“=”称为赋值运算符,它将右边的值赋予左边的变量。
然后是熟悉的printf()语句,但这里的用法和之前稍有不同:
printf("My salary is %d.",salary);
括号内有两个参数,用逗号分开。参数是传递给函数的值。在这个程序语句中,传给printf()函数的两个参数如下:
● 参数1是一个控制字符串,用来控制其后的参数输出以什么方式显示,它是放在双引号内的字符串,也称为格式字符串,因为它指定了输出数据的格式。
● 参数2是变量名salary。这个变量值的显示方式是由第一个参数——控制字符串来确定。
这个控制字符串和前一个例子相当类似,都包含一些要显示的文本。但在本例的这个字符串中有一个%d,它称为变量值的转换说明符(conversion specifier)。
转换说明符确定变量在屏幕上的显示方式,换言之,它们指定最初的二进制值转换为什么形式,显示在屏幕上。在本例中使用了d,它是应用于整数值的十进制说明符,表示第二个参数salary输出为一个十进制数。
注意:
转换说明符总是以%字符开头,以便printf()函数识别出它们。控制字符串中的%总是表示转换说明符的开头,所以如果要输出%字符,就必须用转义序列%%。
试试看:使用更多的变量
试试一个稍大的程序:
// Program 2.3 Using more variables
#include <stdio.h>
int main(void)
{
int brothers; //Declare a variable called brothers
int brides; //and a variable called brides
brothers = 7; //Store 7 in the variable brothers
brides = 7; //Store 7 in the variable brides
// Display some output
printf("%d brides for %d brothers\n", brides, brothers);
return 0;
}
执行程序的结果如下:
7 brides for 7 brothers;
代码的说明
这个程序和前一个例子相当类似。首先声明两个变量brothers和brides,语句如下:
int brothers; //Declare a variable called brothers
int brides; //and a variable called brides
两个变量都声明为int类型,都存储整数值。注意,它们在两个语句中声明。由于这两个变量的类型相同,故可以将它们放在同一行代码上声明:
int brothers, brides;
在一个语句中声明多个变量时,必须用逗号将数据类型后面的变量名分开,该语句要用分号结束。这是一种很方便的格式,但有一个缺点:每个变量的作用不很明显,因为它们全放在一行代码上,不能加入注释来描述每个变量。因此可以将它们分成两行,语句如下:
int brothers, //Declare a variable called brothers
brides; //and a variable called brides
将语句分成两行,就可以加入注释了。这些注释会被编译器忽略,因此和最初没加入注释的语句相同。可以将C语句分成好几行。分号决定语句的结束,而不是代码行的结束。
当然也可以编写两个声明语句。一般最好在一个语句中定义一个变量。变量声明常常放在函数的可执行语句的开头,但这不是必须的。一般把要在一块代码中使用的变量声明放在该起始括号的后面。
之后的两个语句给两个变量赋值7:
brothers = 7; // Store 7 in the variable brothers
brides = 7; // Store 7 in the variable brides
注意,声明这些变量的语句放在上述语句之前。如果遗漏了某个声明,或把声明语句放在后面,程序就不会编译。变量在其声明之前在代码中是不存在的,必须总是在使用变量之前声明它。
下一个语句调用printf()函数,它的第一个参数是一个控制字符串,以显示一行文本。这个字符串还包含规范,指定后续参数的值如何解释和显示在文本中。这个控制字符串中的两个转换说明符%d会分别被printf()函数的第二个参数brides和第三个参数brothers的值取代:
printf("%dbrides for %d brothers\n", brides, brothers);
转换说明符按顺序被printf()函数的第二个参数brides和第三个参数brothers的值取代:变量brides的值对应第一个%d,变量brothers的值对应第二个%d。如果将设置变量值的语句改为如下所示,将会更清楚:
brothers = 8; // Store 8 in the variable brothers
brides = 4; // Store 4 in the variable brides
在这个比较明确的例子中,printf()语句会清楚地显示变量和转换说明符的对应关系,因为输出如下所示:
4 brides for 8 brothers
为了演示变量名是区分大小写的,修改printf()函数,使其中一个变量名以大写字母开头,如下所示:
// Program 2.3A Using more variables
#include <stdio.h>
int main(void)
{
int brothers; // Declare a variable called brothers
int brides; // and a variable called brides
brothers = 7; // Store 7 in the variable brothers
brides = 7; // Store 7 in the variable brides
// Display some output
printf("%d brides for %d brothers\n", Brides, brothers);
return 0;
}
编译这个版本的程序时,会得到一个错误信息。编译器把brides和Brides解释为两个不同的变量,所以它不理解Brides这个变量,因为没有声明它。这是一个常见的错误,如前所述,打字和拼写错误是出错的一个主要原因。变量必须在使用之前声明,否则编译器就无法识别,将该语句标识为错误。
前面介绍了如何声明及命名变量,但这和在第一章学到的知识相比并没有太多用处。下面编写另一个程序,在产生输出前使用变量的值。
试试看:作一个简单的计算
这个程序用变量的值做简单的计算:
// Program 2.4 Simple calculations
#include <stdio.h>
int main(void)
{
int total_pets;
int cats;
int dogs;
int ponies;
int others;
// Set the number of each kind of pet
cats = 2;
dogs = 1;
ponies = 1;
others = 46;
// Calculate the total number of pets
total_pets = cats + dogs + ponies + others;
printf("We have %d pets in total\n", total_pets); // Output the result
return 0;
}
执行程序的结果如下:
Wehave 50 pets in total
代码的说明
与前面的例子一样,大括号中的所有语句都有相同的缩进量,这说明这些语句都包含在这对大括号中。应当仿效此法组织程序,使位于一对大括号之间的一组语句有相同的缩进量,使程序更易于理解。
首先,定义5个int类型的变量:
int total_pets;
int cats;
int dogs;
int ponies;
int others;
因为这些变量都用来存放动物的数量,它们肯定是整数,所以都声明为int类型。
下面用4个赋值语句给变量指定特定的值:
cats = 2;
dogs = 1;
ponies = 1;
others = 46;
现在,变量Total_Pets还没有设定明确的值,它的值是使用其他变量进行计算的结果:
total_pets= cats + dogs + ponies + others;
在这个算术语句中,把每个变量的值加在一起,计算出赋值运算符右边的所有宠物数的总和,再将这个总和存储到赋值运算符左边的变量Total_Pets中。这个新值替代了存储在变量Total_Pets中的旧值。
printf()语句显示了变量Total_Pets的值,即计算结果:
printf("Wehave %d pets in total\n", total_pets);
试着改变某些宠物的值,或增加一些宠物。记住要声明它们,给它们设定数值,将它们加进变量Total_Pets中。
在上面的例子,用下面的语句声明每个变量:
intcats; //The number of cats as pets
用下面的语句设定变量Cats的值:
Cats = 2;
将变量Cats的值设为2。这个语句执行之前,变量的值是什么?它可以是任何数。第一个语句创建了变量Cats,但它的值是上一个程序在那块内存中留下的数值。其后的赋值语句将变量Cats的值设置为2。但最好在声明变量时,就初始化它,语句如下所示:
int Cats = 2;
这个语句将变量Cat声明为int类型,并设定初值为2。声明变量时就初始化它一般是很好的做法。它可避免对初始值的怀疑,当程序运作不正常时,它有助于追踪错误。避免在创建变量时使用垃圾值,可以减少程序出错时计算机崩溃的机会。随意使用垃圾值可能导致各种问题,因此从现在起,就养成初始化变量的好习惯,即使是0也好。
上面的程序是第一个真正做了些事情的程序。它非常简单,仅仅相加了几个数字,但这是非常重要的一步。它是运用算术语句进行运算的一个基本例子。下面介绍一些更复杂的计算。
在C语言中,算术语句的格式如下:
变量名= 算术表达式;
赋值运算符右边的算术表达式指定使用变量中存储的值和/或明确给出的数字,以及算术运算符如加(+)、减(-)、乘(*)及除(/)进行计算。在算术表达式中也可以使用其他运算符,如后面所述。
前面例子中的算术语句如下:
total_pets= cats + dogs + ponies + others;
这个语句先计算等号右边的算术表达式,再将所得的结果存到左边的变量中。
在C语言中,符号“=”定义了一个动作,而不是像数学中那样说明两边相等。它指定将右边表达式的结果存到左边的变量中。因此可以编写下面的语句:
total_pets= total_pets + 2;
以数学的观点来看,它是很荒唐的,但对编程而言它是正确的。假定重新编写程序,添加上面的语句。添加了这个语句的程序段如下:
total_pets = cats + dogs + ponies + others;
total_pets =total_pets + 2;
printf("The total number of petsis: %d", total_pets);
在执行完第一个语句后,Total_Pets的值是50。之后,第二行提取Total_Pets的值,给该值加2,再将结果存储回变量Total_Pets。因此最后显示出来的总数是52。
注意:
在赋值运算中,先计算等号右边的表达式,然后将结果存到等号左边的变量中。新的值取代赋值运算符左边的变量中的原值。赋值运算符左边的变量称为lvalue,因为在这个位置可以存储一个值。执行赋值运算符右边的表达式所得的值称为rvalue,因为它是计算表达式所得的一个值。
计算结果是数值的表达式称为算术表达式,下面都是算术表达式:
3 1 + 2 total_pets cats + dogs – ponies -data
计算这些表达式,都会得到一个数值。注意,变量名也是一个表达式,它的计算结果是一个值,即该变量包含的值。最后一个例子的值是data的负值,所以如果data包含-5,表达式-data的值就是5。当然,data的值仍是-5。稍后将详细讨论如何构建表达式,并学习运算规则。这里先用基本算术运算符做一些简单的例子。表2-1列出了这些算术运算符。
表2-1 基本算术运算符
运 算 符 |
动 作 |
+ |
加 |
- |
减 |
* |
乘 |
/ |
除 |
% |
取模(Modulus) |
应用运算符的数据项一般称为操作数,两边的操作数都是整数时,所有这些运算符都生成整数结果。前面没有提到过取模运算符。它用运算符左边的表达式值去除运算符右边的表达式值,并求出其余数,所以有时称为余数运算符。表达式12 % 5的结果是2。因为12除以5的余数是2。下一节将详细介绍。所有这些运算符的工作方式都与我们的常识相同,只有除法运算符例外,它应用于整数时有点不直观。下面进行一些算术运算。
注意:
应用运算符的值称为操作数。需要两个操作数的运算符(如%)称为二元运算符。应用于一个值的运算符称为一元运算符。因此-在表达式a-b中是二元运算符,在表达式-data中是一元运算符。
试试看:减和乘
下面基于食物的程序演示了减法和乘法:
// Program 2.5 Calculations with cookies
#include <stdio.h>
int main(void)
{
int cookies = 5;
int cookie_calories = 125; //Calories per cookie
int total_eaten = 0; //Total cookies eaten
int eaten = 2; // Number to be eaten
cookies = cookies - eaten; // Subtract number eaten fromcookies
total_eaten = total_eaten + eaten;
printf("\nI have eaten %d cookies. There are %d cookies left",
eaten, cookies);
eaten = 3; // New value for cookies eaten
cookies = cookies - eaten; // Subtract number eaten from cookies
total_eaten = total_eaten + eaten;
printf("\nI have eaten %d more. Now there are %d cookiesleft\n", eaten, cookies);
printf("\nTotal energy consumed is %dcalories.\n", total_eaten*cookie_calories);
return 0;
}
这个程序产生如下输出:
I have eaten 2 cookies. There are 3 cookies left
I have eaten 3 more. Now there are 0cookies left
Total energy consumedis 625 calories.
代码的说明
首先声明并初始化3个int类型的变量:
int cookies = 5;
int cookie_calories =125; //Calories per cookie
int total_eaten = 0; //Total cookies eaten
在程序中,使用变量total_eaten计算吃掉的饼干总数,所以要将它初始化为0。
下一个声明并初始化的变量存储吃掉的饼干数,如下:
inteaten = 2; // Number to be eaten
用减法运算符从cookies中减掉eaten:
cookies= cookies - eaten; //Subtract number eaten from cookies
减法运算的结果存回cookies变量,所以cookies的值变成3。因为吃掉了一些饼干,所以要给total_eaten增加吃掉的饼干数:
total_eaten= total_eaten + eaten;
将eaten变量的当前值2加到total_eaten的当前值0上,结果存储回变量total_eaten。printf()语句显示剩下的饼干数:
printf("\nI have eaten %d cookies. There are%d cookies left",
eaten, cookies);
这个语句在一行上放不下,所以在printf()的第一个参数后的逗号后面,将该语句的其他内容放在下一行上。可以像这样分拆语句,使程序易于理解,或放在屏幕的指定宽度之内。注意不能用这种方式拆分第一个字符串参数。不能在字符串的中间放置换行符。需要将字符串拆开成两行或多行时,一行上的每一段字符串必须有自己的一对双引号。例如,上面的语句可以写成:
printf("\nI have eaten %d cookies. "
" There are %d cookies left",
eaten, cookies);
如果两个或多个字符串彼此相邻,编译器会将它们连接起来,构成一个字符串。
用整数值的转换说明符%d将eaten和cookies的值显示出来。在输出字符串中,eaten的值取代第一个%d, cookies的值取代第二个%d。字符串在显示之前会先换行,因为开头处有一个\n。
下一个语句将变量eaten的值设为一个新值:
eaten= 3; // New value for cookies to beeaten
新值3取代eaten变量中的旧值2。然后完成和以前一样的操作序列:
cookies = cookies - eaten; // Subtract numbereaten from cookies
total_eaten =total_eaten + eaten;
printf("\nI have eaten %d more.Now there are %d cookies left\n", eaten, cookies);
最后,在执行return语句,结束程序前,计算并显示被吃掉饼干的卡路里数:
printf("\nTotalenergy consumed is %d calories.\n", total_eaten*cookie_calories);
printf()函数的第二个参数是一个算术表达式,而不是变量。编译器会将表达式total_eaten*cookie_calories的计算结果存储到一个临时变量中,再把该值作为第二个参数传送给printf()函数。函数的参数总是可以使用算术表达式,只要其计算结果是需要的类型即可。
下面看看除法和取模运算符。
试试看:除法和取模运算符
假设你有一罐饼干(其中有45块饼干)和7个孩子。要把饼干平分给每个孩子,计算每个孩子可得到几块饼干,分完后剩下几块饼干。
// Program 2.6 Cookies and kids
#include <stdio.h>
int main(void)
{
int cookies = 45; //Number of cookies in the jar
int children = 7; //Number of children
int cookies_per_child = 0; //Number of cookies per child
int cookies_left_over = 0; // Number of cookiesleft over
// Calculate how many cookies each child gets when they are divided up
cookies_per_child = cookies/children; //Number of cookies per child
printf("You have %d children and %d cookies\n", children,cookies);
printf("Give each child %d cookies.\n",cookies_per_child);
// Calculate how many cookies are left over
cookies_left_over = cookies%children;
printf("There are %d cookies left over.\n", cookies_left_over);
return 0;
}
执行程序后的输出:
You have 7 children and 45 cookies
Give each child 6cookies.
There are 3 cookiesleft over.
代码的说明
下面一步一步地解释这个程序。下面的语句声明并初始化4个整数变量:cookies、children、cookies_per_child、cookies_left_over:
int cookies = 45; // Number of cookies in the jar
int children = 7; // Number of children
int cookies_per_child= 0; //Number of cookies per child
int cookies_left_over = 0; //Number of cookies left over
使用除号运算符“/”将饼干数量除以孩子的数量,得到每个孩子分得的饼干数:
cookies_per_child= cookies/children; //Number of cookies per child
下面两个语句输出结果,即cookies/children变量的值:
printf("You have %d children and %dcookies\n", children, cookies);
printf("Give each child %dcookies.\n", cookies_per_child);
从输出结果可以看出,cookies_per_child的值是6。这是因为当操作数是整数时,除法运算符总是得到整数值。45除以7的结果是6,余3。下面的语句用取模运算符计算余数:
cookies_left_over= cookies%children;
赋值运算符右边的表达式计算cookies除以children得到的余数。最后一个语句输出余数:
printf("Thereare %d cookies left over.\n", cookies_left_over);
当一个操作数是负数时,使用除法和模数运算符的结果是什么?在执行除法运算时,如果操作数不同号,结果就是负数。因此,表达式-45/7和45/-7的结果相同,都是-6。如果操作数同号,都是正数或都是负数,结果就是正数。因此45/7和-45/-7结果都是6。至于模数运算符,不管操作数是否同号,其结果总是和左操作数的符号相同。因此45%-7等于3,-45/7等于-3,-45/-7也等于-3。
例如,乘法运算符是一个二元运算符。因为它有两个操作数,其结果是一个操作数乘以另一个操作数。还有一些运算符是一元运算符,即它们只需一个操作数。后面将介绍更多的例子。但现在看看一个最常用的一元运算符。
前面使用的运算符都是二元运算符,因为它们都操作两个数据项。C语言中也有操作一个数据项的一元运算符。一元减号运算符就是一个例子。若操作数为负,它就生成正的结果,若操作数为正,它就生成负的结果。要了解一元减号运算符的使用场合,考虑一下追踪银行账号。假定我们在银行存了200元。在簿子里用两列记录这笔钱的收支情况,一列记录付出的费用,另一列记录得到的收入,支出列是负数,收入列是正数。
我们决定购买一片价值50元的CD和一本价值25元的书。假使一切顺利,从银行的初始值中减掉支出的75元后,就得到了余额。表2-2说明这些项的记录情况。
表2-2 收入与支出记录
项 |
收 入 |
支 出 |
存 款 余 额 |
支票收入 |
$200 |
|
$200 |
CD |
|
$50 |
$150 |
书 |
|
$25 |
$125 |
结余 |
$200 |
$75 |
$125 |
如果将这些数字存储到变量中,可以将收入及支出都输入为正数,只有计算余额时,才会把这些数字变成负数。为此,可以将一个负号(-)放在变量名的前面。
要把总支出输出为负数,可编写如下语句:
int expenditure = 75;
printf("Your balance has changedby %d.", -expenditure);
这会产生如下结果:
Yourbalance has changed by -75.
负号表示花掉了这笔钱,而不是赚了。注意,表达式-expenditure不会改变expenditure变量的值,它仍然是75。这个表达式的值是-75。
在表达式-expenditure中,一元减号运算符指定了一个动作,其结果是翻转expenditure变量的符号:将负数变成正数,将正数变成负数。这和编写一个负数(如-75或-1.25)时使用的负号运算符是不同的。此时,负号不表示一个动作,程序执行时,不需要执行指令。它只是告诉编译器,在程序里创建一个负的常量。