运算符是程序中用于数值运算的操作符,C 语言的运算符可分为 算术运算符、关系与逻辑运算符 和 位操作运算符 这 3 类。
2.6.1 算术运算符
算术运算符用来完成基本的数值运算,如 加、减、乘、除,它们可用于所有的数据类型。如下表所示,列出了C语言所有的算术运算符。其中,“-”运算符即能表示两个操作数的减法运算,又能对一个操作数进行取反运算,将正数变为负数,或将负数变为正数。取模运算是取得两数相除的余数。
2.6.2 自增 和 自减
自增和自减体现了 C 语言语法的简洁,自增就是在原值的基础上加一,自减则是减一。它的使用格式是“变量++”或“++变量”,等同于“变量 = 变量 + 1”表达式。这两个运算符又称一目运算符,即参与运算的操作数只有一个。自增和自减操作符与变量间的位置不同也会有不同的运算效果,如下例所示:
int a = 5; // 声明整型变量并赋值 printf("a = %d ", a++); // 输出变量的值后,再使变量自增 printf("a = %d " , ++a); // 变量自增后,再输出变量的值
代码中第 2 行输出的值为 5,因为先输出了变量的值,然后才使变量的值加 1。而运行到第 3 行时,输出的值为 7,变量在被输出前,已执行了自增运算。
运算符执行的顺序不同,代表着运算符有着不同的优先级。通常一目算术运算符的优先级最高,其次是基本的算术运算符,加、减、乘、除、取模,它们之间的优先级与算术运算相同,先乘、除、取模后加、减;优先级最低的是赋值运算。自增和自减运算与变量的位置决定着其优先级是最高还是最低。如下例所示:
int a = 5, b = 7, c = 20; // 声明整型变量并赋值 c = c + -a * b -c % b++; // 使用表达式为变量
这个例子的运算结果是 -21,代码第 2 行的表达式中最先运算的是 -a,为变量 a 取反,然后是从左向右结合的乘法运算和取模运算,再然后是从左向右结合的加、减法运算,接着是赋值运算,最后才是自增运算。
如果在表达式之中使用小括号,则会改变优先级,最里层括号内的表达式会被优先计算,但不包括一目运算符。代码如下:
int a = 5, b = 7, c = 20; // 声明整型变量并赋值 c = c + -a * ( ( b - c ) % b++ ); // 使用表达式为变量
这个例子的运算结果是 50,因为取反运算符和最里层括号内的表达式 b -c 最先被计算,然后再计算外层括号中的表达式,最后进行加法运算和赋值操作。
2.6.3 关系 和 逻辑 运算符
关系运算符用于比较两个数据间的差异,大于、小于 和 等于 是基本的关系运算符。逻辑运算符用于数值间的逻辑演算,与、或、非是基本的逻辑运算符。关系运算符和逻辑运算符关系密切,因此常划为一个类别。C语言中可用的关系和逻辑运算符如下表所示。
关系 和 逻辑 运算符 | |||
---|---|---|---|
运算符 | 说明 | 运算符 | 说明 |
> | 大于 | != | 不等于 |
< | 小于 | && | 与 |
<= | 大于或等于 | || | 或 |
>= | 小于或等于 | ! | 非 |
== | 等于 |
注意:或运算符 “||” 是通过两次按下键盘上的竖线输入的,即 “Shift + ”。另外,等于操作符 “==” 和赋值操作符 “=” 的意义完全不同。
关系 和 逻辑 运算符 用 “真” 和 “假” 表示运算结果。C语言中,非 0 的值在关系运算中都可以表示为 “真”, 0 表示为 “假”。它们有一套专门的计算方法,这套计算方法称之为逻辑运算,逻辑运算的结果用整型数据 1 表示 “真”,整型数据 0 表示 “假”。为了计算简便,下表推演出逻辑真值表:
逻辑真值表 | ||||
---|---|---|---|---|
p | q | p && q | p || q | !p |
0 | 0 | 0 | 0 | 1 |
0 | 非 0 | 0 | 1 | 1 |
非 0 | 非 0 | 1 | 1 | 0 |
非 0 | 0 | 0 | 1 | 0 |
该表是根据 p 和 q 的取值来计算逻辑表达式的值。关系 和 逻辑 运算符中,优先级最高的仍然是一目运算符 “!”,其次是关系运算符 “>=” 和 “<=”,再次是 “==” 和 “!=”,其后是 “&&”,最低是 “||”。同算术表达式一样,在关系或逻辑表达式中也可用括号来修改计算顺序。
2.6.4 位操作符
位操作是计算机底层的运算方式,与组成计算机的逻辑电路运行模式一致,C 语言支持全部的位操作符。因为 C语言的设计目的是取代汇编语言,所以它必须支持汇编语言所具有的运算能力。位操作是对字节或字中的位进行测试、置位或移位处理,这里字节或字是针对 C 标准中的字符型和整型数据类型而言的。位操作不能用于浮点型、空值或其他复杂类型。下表给出了位操作的操作符。
位操作符 | |||
---|---|---|---|
运算符 | 说明 | 运算符 | 说明 |
& | 按位与 | ~ | 1 的补码 |
| | 按位或 | >> | 右移 |
^ | 按位异或 | << | 左移 |
位操作中的与、或 和 1 的补码的真值表与逻辑运算等同,唯一不同的是位操作是逐位进行运算的,即比较操作数的每一个二进制位。如果两个操作数长度不一样,则将较短的操作数高位全部补 0。位操作增加了异或运算,下表是异或运算的逻辑真值表。
异或运算逻辑真值表 | |||||
---|---|---|---|---|---|
p | q | p ^ q | p | q | p ^ q |
0 | 0 | 0 | 1 | 1 | 0 |
0 | 1 | 1 | 1 | 0 | 1 |
2.6.5 问号操作符
问号操作符是最简单的条件语句,格式为:
条件表达式 ? 表达式 1 : 表达式 2;
问号操作符是 C 语言内唯一的三目运算符。其作用是在条件表达式为真的情况下,执行表达式 1,否则执行表达式 2。如下例所示:
int a = 5, b = 7; // 声明整型变量并赋值 a > b ? b++ : b--; // 当 a 大于 b 时,b 自增,否则 b 自减
显而易见,此例执行了一个表达式 b--。需要说明的是,问号操作符比一般的运算符优先级要低,仅次于后置的自增和自减。
2.6.6 逗号操作符
逗号操作符用于将多个表达式连接在一起。逗号操作符的左侧总是作为空值,如果要取得整个表达式的值,只有逗号表达式右侧的值是有效的。如下例所示:
int a = 5, b = 7; // 声明整型变量并赋值 b = ( a + b, a - b ); // 用表达式的结果为变量 b 赋值
代码第二行,b 的值变为 -2。因为第一个表达式 a + b 的计算结果作为空值被忽略,第二个表达式a - b 的计算结果被赋值给了 b。因为逗号操作符的优先级比赋值操作符优先级低,所以必须使用括号。
2.6.7 优先级
下表列出了 C 语言所有操作符的优先级,其中包括将后面要讨论的某些操作符。除一元操作符和问号操作符之外,所有操作符都是左结合的。一元操作符及问号操作符则为右结合。
C语言操作符的优先级 | |
---|---|
优先级最高 ↓ 优先级最低 |
() [] -> |
! ~ ++ -- -(type) * & sizeof | |
* / % | |
+ - | |
<< >> | |
<= >= | |
== != | |
& | |
^ | |
| | |
&& | |
|| | |
? | |
= += -= *= /= | |
, |