一、关系运算符
C 提供的关系运算符(Relational
Operator)如下:
>
大于运算符
>=
大于或等于运算符
==
等于运算符(注意别和赋值运算符混淆了)
<=
小于或等于运算符
<
小于运算符
!= 不等于运算符
关系运算符可以直接应用于复数类型以外的全部基本数据类型。对于复数类型,正如数学上所定义的一样,只能比较是否相等,而不能比较大小。关系运算符常用于控制循环。如:
while ( i != 10
) /* 只要 i 不等于 10
*/
++i; /*
i 自增 */
while ( i == 10
) /* 只要 i 等于 10
*/
{
sum =
sum + i; /* 将 sum 的值增 10
*/
scanf("%d", &i); /* 将用户输入保存于 i
*/
}
while ( ch != '#'
) /* 只要 ch 的值不等于 '#'
*/
{
cnt++;
/* cnt 增
1
*/
scanf(
"%c", &ch ); /*
接收用户输入
*/
}
关系运算符应用于字符型对象时,比较的是字符所对应的编码。对于使用 ASCII 的计算机来说,# 的码值是 35,所以 ch != '#' 实际上就是判断
ch 的值是否为 35。
使用关系运算符比较浮点数时,最好只用 < 和
>,而不要使用其它关系运算符。这是因为,目前浮点数在计算机中的表示存在误差,可能导致两个本应相等的浮点数在计算机中却表现为不相等。如果非要比较两个浮点数是否相等,常用的办法是比较它们的差的绝对值是否小于某个较小的数(如
0.00001),也就是比较它们是否大致相等。至于这个较小的数到底取多小,可以根据程序对精准度的要求以及浮点数本身的精准度(标准规定 float
至少精确到小数点后 6 位,double 至少精确到小数点后 10 位)选定。为了求出这两个浮点数的差的绝对值,就要用到标准函数库里的 fabs 函数。fabs
函数声明于标准头文件 math.h,正如使用 printf 和 scanf 等标准输入输出函数要包含 stdio.h 头文件一样,使用 fabs
要求我们在源文件中包含 math.h。例如:
/* compare floating-point numbers
*/
#include
<math.h>
#include <stdio.h>
#define E
0.00000001
int
main(void)
{
const
double ANSWER =
1.23456;
double guess;
printf("Guess my value:
");
scanf("%lf",
&guess);
if ( fabs(guess - ANSWER) < E ) // 判断 guess 是否大致等于
ANSWER
{ // 如果大致相等,则输出 You got it!
并换行
printf("You got
it!\n");
}
else
{ // 反之,输出 You're
wrong! 并换行
printf("You're
wrong!\n");
}
return
0;
}
如果您不懂 if 语句的用法,请参考 46. if
语句 。
我们把 a < b,x != y
等使用了关系运算符的表达式称为关系表达式。关系表达式非假(false)即真(true),绝对没有第三种结果。以 x != y 为例,如果 x 不等于 y,则 x
!= y 为真,否则为假。C 语言中,0 为假,非零为真。但是,如果表达式为真,则其值为 1,反之,其值为 0 。例如:
#include
<stdio.h>
int
main(void)
{
/* 1 ==
1 为真,1 != 1 为假
*/
printf("%d, %d\n", 1 == 1, 1 != 1);
return
0;
}
编译运行此程序,结果为:1, 0 。
因此,以下代码
while ( 1 ) /* 1 或者其它任何非零值
*/
{
/* ... ...
*/
}
是一个无限循环(死循环)。因为 1 永远为真,所以这个循环会一直进行下去,直到程序被强制关闭。又如:
while ( count
)
{
/* ... ...
*/
}
只要 count 的值不为 0,则循环会一直进行下去,直到 count 的值变成 0 为止。
不要把赋值运算符 = 和 等于运算符 == 混淆了。在该用 == 的时候却误用 =
会导致很多意想不到的结果。例如:
while ( count = 8
)
{
/* ... ...
*/
}
因为 = 左边的变量的值即为赋值表达式的值,所以 count = 8 的值永远为 8,故而这是一个死循环。把 = 替换成 == ,则当
count 的值不等于 8 时,循环结束。
鉴于此,在使用等于运算符时,有些程序员习惯将常量放在表达式左边,把变量放在右边:
8 == count
// 检查 count 的值是否等于 8
8 =
count // 语法错误,赋值运算符左边必须为可变左值
如此,如果错把 == 写成了 = ,在编译时就会报错,从而避免了误用 = 导致的意想不到的结果。
二、关系运算符的优先级
关系运算符的优先级比算术运算符低,比赋值运算符高。所谓算术运算符,是指:
+ -
正负运算符 单目
* 乘法运算符
双目
/
除法运算符 双目
% 模除运算符
双目
+
加法运算符 双目
- 减法运算符 双目
这些运算符的用法我们在前面的教程中已经说了。由关系运算符的优先级,可知
x > y + 2
等同于
x > (y + 2) // 如果 x 大于 y
+ 2,则此表达式为真
而
x = y > 2
等同于
x = (y > 2) // 如果 y >
2 为真,则 x 的值变成 1;反之,x 的值变成 0
< 、<= 、> 以及 >= 拥有相同的优先级,并且比 == 和 != 的优先级高。== 和 !=
的优先级相同。和其它大多数运算符一样,关系运算符的结合律也是从左到右。因此:
x != y == z
等同于
(x != y) == z
首先,运算 x != y 得到 1 或者 0,然后 1 或者 0 用于和 z
比较。尽管我们可以这么写,但是这种代码实在是晦涩难懂,并且不利于维护,所以我们最好不要写这种代码。
下表概括了我们到目前为止学过的运算符的优先级及其结合律,按照优先级从高到低进行排列,相同优先级的运算符放在同一行。
注意,上图第二行中的 (类型名) 指的是类型转换运算符。
参考资料:C Primer 5th
Edition
The C
Programming Language 2nd
Edition
C99 标准
本文版权归 蚂蚁的 C/C++ 标准编程 以及 作者 antigloss 共同所有,转载请注明原作者和出处。谢谢。