算术运算符及算术表达式,C语言算术运算符及算术表达式详解

算术运算符按操作数个数可分为一元运算符(含一个操作数)和二元运算符(含两个操作数)。一元运算符的优先级一般高于二元运算符

一元运算符:+(正号)、-(负号)、++(增1)、--(减1)。

二元运算符:+(求和)、-(求差)、*(求积)、/(求商)、%(求余)。

符号运算符:+(正号)、-(负号)

'+'(正号)表示不改变操作数的值及符号,如 23 也可表示为 +23,编译器不报错。而 '-'(负号)可用于得到一个数的相反数。例如:
int a=-5;
int b=-a;
在变量 a 前加 -(负号)后赋值给 b,即把 a 的相反数赋给 b。

自增量运算符:++(增1)、--(减1)

自增量运算符均有两种使用形式,++a、a++ 及 --a、a--,也称为前缀形式后缀形式

在讲解自增量运算符的两种形式之前,先介绍下左值(lvalue)和右值(rvalue)的概念。

计算机内存中可修改的存储对象,一般称为左值 lvalue例如:
int a; //整型变量a可以作为左值使用
float b; //单精度浮点型变量b也可作为左值使用
const int c; //因为常变量c的值不允许改变,故不可作为左值使用
把可赋值给左值的量称为右值 rvalue。右值可以是常量、变量或者表达式。例如:
int a,b; //定义整型变量a和b
a=2; //把常量2作为右值,赋给左值a
b=a; //把变量a作为右值,赋给左值b
b=a+3; //把表达式a+3的值作为右值,赋给左值b
前缀形式:如 ++a 为前缀加形式的增 1 表达式,表示把变量 a 的值加 1 后的值作为该表达式的值,同时变量 a 本身的值加 1; --a 类似,表示把变量 a 的值减 1 后的值作为该表达式的值,同时变量 a 本身的值减 1。

例如:
int a=5,b;
则语句 b=a++; 与 b=++a; 的含义不同。若采用第一条赋值语句,则直接把 a 的原值 5 赋给变量 b。若采用第二条赋值语句,则把 a 的原值 5 加 1 后的值 6 赋给变量 b。相同的是,这两种赋值方式均使变量 a 自身的值增了1,即执行完后,a 均为6。

后缀形式:如 a++为后缀加形式的增 1 表达式,表示先直接把变量 a 原来的值作为该表达式的值,然后变量 a 本身的值加 1; a-- 类似,表示先直接把变量 a 原来的值作为该表达式的值,然后变量 a 本身的值减 1。

注意,浮点型变量也同样支持自增量运算操作。例如:
float a=3.2f;
a++;
printf("a=%f\n",a);
执行完自增量运算后,输出 a=4.200 000。

建议在实际编程中,应尽量避免对浮点型变量进行自增量运算操作。通过下面的例子,掌握前缀增1 与后缀增 1 两种使用形式的异同。

【例 1】分析以下程序,输出其运行结果。
#include<stdio.h>
int main (void)
{
    int a=2,b,c,d;
    b=++a+4;
    c=3*a++;
    d=a--*3;
    printf ("a=%d,b=%d,c=%d,d=%d",a,b,c,d);
    return 0;
}
代码分析:
1) b=++a+4;该语句中运用到三个运算符:前缀增 1 运算符 ++、加法运算符 + 和赋值运算符 =,三个运算符的优先级是一元运算符 ++ 最高,其次是求和,最低的是赋值运算符。

该语句等价于 b=(++a)+4; 先取变量 a 的值 2 加 1 后的结果 3 作为 ++a 表达式的值,然后把该表达式的值 3 与 4 求和的值 1 赋值给变量 b,即 b 值为 7。执行完该语句后变量 a 自身值增 1,其值变为 3。

2) c=3*a++; 等价于 c=3*(a++); 表示把 3 与 a++ 求积的结果赋给 c,而 a++ 表达式表示先把变量 a 的值 3 作为该表达式的值,即 c=3*3; 同时变量 a 自身值增 1,变为 4。

3) d=a--*3; 先取变量 a 的值 4 作为表达式 a-- 的值,把 4*3 的值 12 赋给变量 d。同时变量 a 自身减 1,变为 3。

4) printf("a=%d,b=%d,c=%d,d=%d", a,b,c,d); 双引号中有 4 个输出格式控制符,依次使用输出列表中 4 个输出项 a、b、c、d 的值替换。

运行结果为:
a=3,b=7,c=9, d=12

增1、减1运算符的副作用

注意,增1、减1运算符是具有副作用的运算符,即不仅能改变表达式的值,也改变了变量自身的值。使用时要慎重,尤其以下两种情况,要避免使用。

1) 当一个变量多次出现在某表达式中时,建议不要将增 1 或减 1 运算符应用于该变量。例如:
int a=1; //定义整型变量a,并赋初值1。
int b; //定义整型变量b,未初始化。
b=a++ + a++; //杜绝编写类似的表达式
a++ + a++ 该表达式的值到底是两次取 a 的原值 1 相加的结果 2 赋给 b,即 b=2=1+1,还是按从左到右取 a 原值 1 作为第一个 a++ 表达式的值,同时变量 a 增 1 变为 2。第二个表达式的值为取 a 的值 2 作为表达式的值,同时变量 a 增 1,变为 3,这样 b=3=1+2,还是从右到左依次运算。C 标准没有对此进行统一规定,不同的编译器可能得到不同的结果。

死记硬背这类操作的规则毫无意义。为了增强代码的可读性及可移植性,并避免产生歧义性,这种非标准的语法一定要慎用或不用。

2) 多参函数调用时,如果一个变量出现在多个实参中时,不要对该变量使用增 1 或减 1 运算符。原因同上,即不同编译器可能得到不同结果,出现歧义性。

相除运算符 /

当运算符 / 的操作数(被除数和除数)均为整数时,结果为取商(取整)。

例如:16/5 结果为两数相除的商 3。

当运算符 / 的操作数中有一个或两个浮点数时,结果与数学中除法运算相同,包含整数部分和小数部分。

例如:8/2.5 结果为 3.2。

取余运算符%

当运算符 % 的操作数(被除数和除数)均为整数时,结果为取余。

例如:16%5 结果为两数相除的余数 1。

当运算符 % 的操作数中有一个或两个浮点数时,语法错误。

例如:8%2.5 语法错误。

即运算符%两操作数都必须为整数,否则语法错误。

在程序设计中,经常使用求商和求余运算符分解整数的各位数字。例如,分解十进制整数 123 的个位、十位和百位数字,可以有多种不同的分解方案,下面是其中一种方案。
int a=123,g,s,b; //g:个位 s:十位 b:百位
g=a%10; //g=3
s=a/10%10; //s=2
b=a/100; //b=l