张银峰的编程课堂

基本运算符

加减乘除+、-、*、/运算符遵循数学运算规则及优先级顺序,这些运算符需要两个操作数。

9 + 10   // 常量 + 常量
a - 20   // 变量 - 常量
a * b    // 变量 * 变量

可以使用多个运算符构建复杂的表达式,如:

10 + b * d / 2

运算符(+、-)也可以作为符号运算符:

  • 负号可以用于指示或改变一个值的代数符号。
  • 正号不改变它的操作数的值或符号,但可以用来强调某些数值的方向性,如坐标点正负。

可以看到,同一运算符可以有多种语义,如 '-',可以表达相减与负号的含义。

  • 表达相减语义时,需要两个操作数,如:a-b,我们将它归属于双目运算符。
  • 表达负号语义时,需一个操作数,我们称之为单目运算符。

除法运算符(/)代表两数相除,整型与浮点型除法运算有很大的不同。

  • 浮点类型的除法运算得出一个浮点数结果。
  • 整数除法运算则产生一个整数结果,不会有小数部分。

这就是说,两个int类型的数据做除法时,结果是其商。当出现不能被整除的情况时,并不会得到小数部分,1/2的结果是0而非0.5,3/2会得到1,这个过程被称为截尾。当需要保留小数部分时,就需要两个浮点类型(如:double)的数值进行运算。除法运算的结果正负取舍和算数一样,符号相同为正,相异为负。

取模运算

取模运算符(%),仅用于整型类型,结果是两个数相除的余数,也可称为求余运算符,如:

  • 2 % 3 读作“对2除以3取模”,模为2。
  • 6 % 3 结果为0。

当操作数中有负数时,取模结果的 正负和被除数符号相同。 即:

  • 如果第一个操作数为负数,那么得到的模也为负数。
  • 如果第一个操作数为正数,那么得到的模也为正数。

取模是一个非常有用的运算,像我们在网页上看到的一些表格文件,奇偶行以两种不同的背景色交替填充,这可以使用取模运算来控制,方法是使用当前行号与2取模,根据结果进行颜色选择并填充。

#include <stdio.h>

int main()
{
    printf( "-3 / 16 = %d\n", -3/16 );
    printf( "16 / -3 = %d\n", 16/-3 );

    printf( "-3 %% 16 = %d\n", -3%16 );
    printf( "16 %% -3 = %d\n", 16%-3 );

    return 0;
}

glimix.com

代码展示了除法与取模运算的符号方向。注意取模运算的输出,在printf()的格式化字符串中,两个连续的%号使得程序转义输出了一个%号。 这是因为%号自身是格式控制符的一部分,因此需要连续输入两个%号以表示转义输出自身。最后,在做除法与取模运算时,始终提醒自己:0不能为除数!

括号运算符

圆括号()运算符可用于改变表达式的运算优先级。

x + y * 3      // 先求值 y*3,再将 x 与之相加
(x + y) * 3    // 先求值 x+y, 将和与3相乘
(a + (b - c)) * d // 先求值b-c,再求值a + (b-c),最后是上两步的结果与d相乘

逗号表达式

逗号运算符可以将两个或多个表达式连接起来,构成表达式列表,列表中的表达式自左向右逐个求值,整个逗号表达式的值就是最后那个表达式的值。如:

2, 3            // 表达式的值是 3
2, b, c+5       // 表达式的值是 c+5
int a = (3, 5); // a的初始值是5。

优先级

我们已经学习了 =、+、-、*、/、%、()、, 运算符,从算术运算符的角度讲,当它们应用到表达式中时,求值顺序依赖于优先级,这里给出由高到低的排序。

  • ()
  • *、/、%
  • +、-
  • =
  • ,

另一个容易被忽略的是结合性:

  • ()、+、-、*、/ 都是从左向右结合,如: a+b、(c/d-2)。
  • = 是从右向左结合,a=3; 表示将右侧的字面量赋值给左侧的变量。
  • +、- 作为符号运算符时,结合性是从右向左,如: +5、-5,表示将字面量取正或取负。

练习

1 编写一组运用加减乘除运算的程序。

2 在程序中加入除0的代码,运行程序看看是什么结果。

3 编程求数值a的平方与立方,注意选择合适的数据类型。

4 在程序中编写几条空语句,看看它们对程序的影响。

5 编写复杂语句,理解括号运算符对表达式求值的影响。