2.4C++的运算符和表达式 运算符是施加在数据上的重要操作,变量、常量通过操作符组合成C++的表达式,构成 了C++程序的基本要素。本节将介绍C+语言中基本运算符和表达式 2.4.1C++中的基本运算符 运算是对数据的加工过程,而标识不同运算的符号称职运算符,参与运算的数据称为操 作数。表2.3列出了C++中的基本运算符、其优先级及对操作数的结合性。 优先级运算符 算顺序 功能 从右向左结合 全局范围符(单目) 17 从左向右结合 类范围符(双目) 从左向右结合 成员选择符 16 从左向右结合 数组下标符 16 从左向右结合 函数调用 从左向右结合 类型结构 sizeof 从左向右结合 取类型存储大小 +, 从右向左结合 自增,自减 5555 从右向左结合 按位反 从右向左结合 逻辑否 从右向左结合 单目加,单目减 15 从右向左结合 指针操作,取址 从右向左结合 类型转换 ew. delete 从右向左结合 动态空间管理 14 从左向右结合 成员指针选择 13 ,/,% 从左向右结合 从左向右结合 加法类运算 从左向右结合 移位运算 从左向右结合 关系比较 从左向右结合 按位与 8765432 从左向右结合 按位异或 左向右结合 && 从左向右结合 逻辑与 「从左向右结台 或 从左向右结合 条件操作符 =,*=,/,%=,+=, 从右向左结合 =,&=,尸,=从右向左结合 赋值符 从左向右结合 逗号表达式 注:优先级相同的运算符,其执行顺序由该运算符在语句中的位置先后决定。 根据参与运算的操作数的类型不同,运算符可以分为单目运算符(1个操作数)、双目 运算符(2个操作数)、三目运算符(3个操作数)。有一些运算符既可以是单目的,也可以 是双目的,根据赋予该运算符的操作数的不同,运算符具有不同的功能 例如:*pFle varl*var2
2.4 C++的运算符和表达式 运算符是施加在数据上的重要操作,变量、常量通过操作符组合成 C++的表达式,构成 了 C++程序的基本要素。本节将介绍 C++语言中基本运算符和表达式。 2.4.1 C++中的基本运算符 运算是对数据的加工过程,而标识不同运算的符号称职运算符,参与运算的数据称为操 作数。表 2.3列出了 C++中的基本运算符、其优先级及对操作数的结合性。 优先级 运算符 运算顺序 功能 17 17 :: :: 从右向左结合 从左向右结合 全局范围符(单目) 类范围符(双目) 16 16 16 16 16 →,. [ ] ( ) ( ) sizeof 从左向右结合 从左向右结合 从左向右结合 从左向右结合 从左向右结合 成员选择符 数组下标符 函数调用 类型结构 取类型存储大小 15 15 15 15 15 15 15 ++,-- ~ ! +,- *,& () new,delete 从右向左结合 从右向左结合 从右向左结合 从右向左结合 从右向左结合 从右向左结合 从右向左结合 自增,自减 按位反 逻辑否 单目加,单目减 指针操作,取址 类型转换 动态空间管理 14 ->*,.* 从左向右结合 成员指针选择 13 *,/,% 从左向右结合 乘法类运算 12 +,- 从左向右结合 加法类运算 11 > 从左向右结合 移位运算 10 ,>= 从左向右结合 关系比较 9 = =,!= 从左向右结合 等值,不等值比较 8 & 从左向右结合 按位与 7 ^ 从左向右结合 按位异或 6 | 从左向右结合 按位或 5 && 从左向右结合 逻辑与 4 || 从左向右结合 逻辑或 3 ?: 从左向右结合 条件操作符 2 =,*=,/=,%=,+=,—=, >=,&=,|=,^= 从右向左结合 从右向左结合 赋值符 1 , 从左向右结合 逗号表达式 注:优先级相同的运算符,其执行顺序由该运算符在语句中的位置先后决定。 根据参与运算的操作数的类型不同,运算符可以分为单目运算符(1 个操作数)、双目 运算符(2 个操作数)、三目运算符(3 个操作数)。有一些运算符既可以是单目的,也可以 是双目的,根据赋予该运算符的操作数的不同,运算符具有不同的功能。 例如: *pFile; var1*var2;
运算符的优先级和数学运算中的优先级意义相同,它决定了一个操作符在表达式的运算 顺序,优先级越高,运算次序越靠前。而结合性则决定一个操作符对其操作数的运算顺序。 如果一个操作符对其操作数的操作运算是自左向右执行的,则称该操作符是右结合的:反之 如果一个操作符对其操作数的操作运算是自右向左执行的,则称该操作符是左结合实际的 根据操作符表示的运算的性质不同,可以将C++中的操作符分为算术运算、关系运算符 逻辑运算符、赋值运算符、条件运算符、自増自减运算符、位运算符和 sizeof运算符等。下 面分别进行讨论。 算术运算符 表2.4列出了C++中的算术运算符 表2.4C+中的算术运算符 运算符 算操作 例子 取负(单目) varl+var 2 减法(双目)vm1-=var2 varl*var 2 1/var 2 % 取模(余) var 1%var2 对于单目运算符一,其返回值的数据类型与操作数的数据类型相同.对于双目运算符+ 和/,若其两个操作数的数据类型相同,则返回值的数据类型与操作数的数据类型相同 若两操作数的数据类型不同,则返回值的数据类型与字长较长的操作数的数据类型相同。 注意:两个整数相除的结果仍然是整数。若被除数不能被除数整除,则相除的结果将被 取整,其小数部分将被略去。 例如:34/7:12.5%3(非法)35%7 在某些情况下,算术运算表达式会产生某些问题,计算的结果将给出错误或没有定义的 数值,这些情况称为运算异常。对不同的运算异常,将产生不同的后果。在C++中,除数为 零和实数溢出被视为一个严重的错误而导致程序运行的异常终止。而整数溢出则不被认为是 个错误(尽管其运算结果有可能与预期值不同)。因此,在一些与硬件打交道的低级程序 中利用整数溢出查看设备的状态位等。 2、关系运算符 表2.5列出了C艹+中的关系运算符,它们都是双目运算符。关系运算符的返回值只有 逻辑真和逻辑假两种。当两个操作数满足关系运算符所要求的比较关系时,返回整型数1 (真):否则返回整型数0(假)。 表2.5C++中的关系运算符 算符 运算操作 使用例子 小于等于 var2var2 大于等于 var2==var2 不等于 var2=var2 例如:var1=85,var2=91 var3=(varl<var2)+6;∥结果为7
运算符的优先级和数学运算中的优先级意义相同,它决定了一个操作符在表达式的运算 顺序,优先级越高,运算次序越靠前。而结合性则决定一个操作符对其操作数的运算顺序。 如果一个操作符对其操作数的操作运算是自左向右执行的,则称该操作符是右结合的;反之 如果一个操作符对其操作数的操作运算是自右向左执行的,则称该操作符是左结合实际的。 根据操作符表示的运算的性质不同,可以将 C++中的操作符分为算术运算、关系运算符、 逻辑运算符、赋值运算符、条件运算符、自增自减运算符、位运算符和 sizeof 运算符等。下 面分别进行讨论。 1、算术运算符 表 2.4 列出了 C++中的算术运算符。 表 2.4 C++中的算术运算符 运算符 运算操作 例子 - 取负(单目) -var + 加法 var1+var2 - 减法(双目) var1-var2 * 乘法 var1*var2 / 除法 var1/var2 % 取模(余) var1%var2 对于单目运算符-,其返回值的数据类型与操作数的数据类型相同.对于双目运算符+、 -、*和/,若其两个操作数的数据类型相同,则返回值的数据类型与操作数的数据类型相同; 若两操作数的数据类型不同,则返回值的数据类型与字长较长的操作数的数据类型相同。 注意:两个整数相除的结果仍然是整数。若被除数不能被除数整除,则相除的结果将被 取整,其小数部分将被略去。 例如:34/7; 12.5%3(非法) 35%7 在某些情况下,算术运算表达式会产生某些问题,计算的结果将给出错误或没有定义的 数值,这些情况称为运算异常。对不同的运算异常,将产生不同的后果。在 C++中,除数为 零和实数溢出被视为一个严重的错误而导致程序运行的异常终止。而整数溢出则不被认为是 一个错误(尽管其运算结果有可能与预期值不同)。因此,在一些与硬件打交道的低级程序 中利用整数溢出查看设备的状态位等。 2、关系运算符 表 2.5 列出了 C++中的关系运算符,它们都是双目运算符。关系运算符的返回值只有 逻辑真和逻辑假两种。当两个操作数满足关系运算符所要求的比较关系时,返回整型数 1 (真);否则返回整型数 0(假)。 表 2.5 C++中的关系运算符 运算符 运算操作 使用例子 大于 var2>var2 >= 大于等于 var2>=var2 = = 等于 var2= =var2 != 不等于 var2!=var2 例如:var1=85;var2=91; var3=(var1<var2)+6; //结果为 7
注意:(1)、关系运算符的两个操作数可以是任何基本数据类型。 (2)、在进行相等及不相等关系关系运算时,除了两个操作数都有是整型数之外,由 于计算机的存储方式及计算误差,运算结果常常会与预期结果相反。因此,在比较两个实数 (浮点数或双精度型)相等或不等时,常用判断这两个操作数的差值的绝对值小于或大于某 给定的小数值来代替(可靠性高一些)。 3、逻辑运算符 表2.6列出了C++中的逻辑运算符,逻辑运算符用来表示操作数的逻辑关系,其运算 结果是整型数1或0。逻辑运算的结果也可以作为一个整型数用在算术运算中 表2.6C++中的逻辑运算符 运算符 运算操作 使用例子 逻辑反 & 逻辑与 expr&&expr expr llexpr2 注意:在C艹+中,0被看作逻辑假,而其他的非零值(任意基本数据类型)均被视为逻 辑真 4、赋值运算符 赋值运算符“=”将左边的变量值或表达式的值赋给左边的变量,其结果是将一个新的 数值存放在左操作数所占用的内存单元中。 赋值运算也有返回值,该返回值的数值是右操作数的数值,而其数据类型则与左操作数 的数据类型相同。同时,赋值运算的运算次序是从右到左进行的。所以采用多个赋值运算符 可以将多个操作数连接起来,其运算结果是将表达式最右端的操作数的值赋给其左边的各个 操作数。 例如:varl=var2=var3=var4=2 赋值操作符可以与某些算术操作符、关系操作符或位操作符进行复合,产生一个新的双 目操作符,其功能是将该操作符的左、右操作数分别作为相应的算术操作符、关系操作符或 位操作符的左、右操作数进行相应的算术、比较或位操作,再将运算的结果赋给复合操作符 的左操作数。在C++中可以使用的10种复合操作符,具体如下 例如:var1+=var2 等价var=varl+var2; 5、条件运算符 条件运算符是C++中唯一的三目运算符,它的使用较为灵活,在某些情况下可以用来代 替if-else语句。条件运算符的语法形式如下 prl?expr 2: expr3 根据 exprI计算的结果决定计算expr2(结果非0)或expr3(结果为0)。整个表达式的 最终返回结果由表达式expr2或expr3决定 例如:5>6x=5x=8 6、自增、自减运算符 自增运算符“++”和自减运算符“一一”主要用在循环语句中,为循环控制变量提供 格式紧缩的加1和减1运算 例如:i++,等价于i=i计+1
注意:(1)、关系运算符的两个操作数可以是任何基本数据类型。 (2)、在进行相等及不相等关系关系运算时,除了两个操作数都有是整型数之外,由 于计算机的存储方式及计算误差,运算结果常常会与预期结果相反。因此,在比较两个实数 (浮点数或双精度型)相等或不等时,常用判断这两个操作数的差值的绝对值小于或大于某 一给定的小数值来代替(可靠性高一些)。 3、逻辑运算符 表 2.6 列出了 C++中的逻辑运算符,逻辑运算符用来表示操作数的逻辑关系,其运算 结果是整型数 1 或 0。逻辑运算的结果也可以作为一个整型数用在算术运算中。 表 2.6 C++中的逻辑运算符 运算符 运算操作 使用例子 ! 逻辑反 !expr && 逻辑与 expr1&&expr2 || 逻辑或 expr1||expr2 注意:在 C++中,0 被看作逻辑假,而其他的非零值(任意基本数据类型)均被视为逻 辑真。 4、赋值运算符 赋值运算符“=”将左边的变量值或表达式的值赋给左边的变量,其结果是将一个新的 数值存放在左操作数所占用的内存单元中。 赋值运算也有返回值,该返回值的数值是右操作数的数值,而其数据类型则与左操作数 的数据类型相同。同时,赋值运算的运算次序是从右到左进行的。所以采用多个赋值运算符 可以将多个操作数连接起来,其运算结果是将表达式最右端的操作数的值赋给其左边的各个 操作数。 例如:var1=var2=var3=var4=21; 赋值操作符可以与某些算术操作符、关系操作符或位操作符进行复合,产生一个新的双 目操作符,其功能是将该操作符的左、右操作数分别作为相应的算术操作符、关系操作符或 位操作符的左、右操作数进行相应的算术、比较或位操作,再将运算的结果赋给复合操作符 的左操作数。在 C++中可以使用的 10 种复合操作符,具体如下: +=,-=,*=,/=,%=,>=,&=,^=,|=。 例如:var1+=var2; 等价 var1=var1+var2; 5、条件运算符 条件运算符是 C++中唯一的三目运算符,它的使用较为灵活,在某些情况下可以用来代 替 if—else 语句。条件运算符的语法形式如下: expr1?expr2:expr3; 根据 expr1 计算的结果决定计算 expr2(结果非 0)或 expr3(结果为 0)。整个表达式的 最终返回结果由表达式 expr2 或 expr3 决定。 例如:5>6?x=5:x=8; 6、自增、自减运算符 自增运算符“++”和自减运算符“――”主要用在循环语句中,为循环控制变量提供 格式紧缩的加 1 和减 1 运算。 例如: i++; 等价于 i=i+1;
自增和自减运算符对其操作数都进行赋值,且每种运算符都有前缀和后缀两种用法。当 使用前缀用法(例如++i)时,程序首先对该操作数进行引用,再对其进行加1或减1用赋 值:当使用后缀用法(例如ⅱ+)时,程序首先对操作数进行加1或减1及赋值,再对该操 作数进行引用。 例2.9]自增、自减运算符及其不同用法举例 cpp ∥增、自减操作符及其不同用法 #includesiostream h> void maino int varl. var 2 cout>var2(移位的位数) 按位与 varl&var 2
自增和自减运算符对其操作数都进行赋值,且每种运算符都有前缀和后缀两种用法。当 使用前缀用法(例如++i)时,程序首先对该操作数进行引用,再对其进行加 1 或减 1 用赋 值;当使用后缀用法(例如 i++)时,程序首先对操作数进行加 1 或减 1 及赋值,再对该操 作数进行引用。 [例 2.9] 自增、自减运算符及其不同用法举例 //EX2_9.cpp //自增、自减操作符及其不同用法 #include void main() { int var1,var2; var1=10; cout> 右移 var1>>var2(移位的位数) & 按位与 var1&var2
按位异或 var var2 var lva 位运算符将其操作数看作一个二进制位的集合,各二进制位的取值只能是0和1中的 个。通过位运算,程序员可以对某个数据中的特定二进制位进行检测或为给定的二进制位赋 注意:位运算符的操作数只能是基本数据类型中的char和int类型及其各种变体而不支 持 float、 double、void或其他更复杂的数据类型。对于整型数据,由于符号位在不同位运算 符中的处理方法不同,且受到机器类型的影响。因此,为了保证程序运行的正确性,建议使 用 unsigned int类型数据作为位运算符的操作数 利用位运算符来设置及检测奇偶校验位,也可以用于简单的加密程序等。 8、 sizeof运算符 sizeof运算符通知编译程序其操作数在内存中占用的字节数,它返回变量或括号中的类 型修饰符的字节长度。这是在程序编译时确定的,与程序的运行状态无关。其格式如下: sizeof( type specifier); E sizeof(variable name) 使用 sizeof运算符的主要目的是为了增强程序的可移植性,使之不会由于机器表示同- 数据类型时存在字节长度不同而导致程序出错,从而确保程序可以在不同的硬件环境上正常 运行。 2.4.2C++表达式 在C++中,表达式是由运算符、常量、变量和表达式按照一定的语法规则组合而成的 表达式在程序执行时完成一个或多个操作,并最终返回一个结果。若无特别说明,表达式的 返回结果是一个右值,其数据类型由参与运算的数据的数据类型来确定。 当不同数据类型的常量和变量在一个表达式中混合使用时,它们在计算时将被转换成同 数据类型。通常C艹+编译器在进行类型转换时遵循“向上转换”的原则,即将涉及数据I 数据类型转换为其中字长最长的数据类型。转换规则如下所示: (1)所有的char和 short int都被转换为int (2)对所有的foat被转换为 double: (3)对所有的操作数,若其中一个为 long double,则另一个也被转换为 long double (4)否则,如果一个操作数为 double,则另一个也被转换为 double (5)否则,如果一个操作数为long,则另一个也被转换为long; (6)否则,如果一个操作数为 unsigned,则另一个也被转换为 unsigned 在按上述规则进行数据类型转换后,同一表达式中的操作数都变成了相同的数据类型数 据,而表达式的运算结果的数据类型也就是这些数据的数据类型 当然,程序员也可以通过强制类型转换强迫表达式中的某些数据转换为某一特定的数据 类型。强制数据类型的形式如下所示 (type-specifier ) variable(u:( double)var;
^ 按位异或 var1^var2 | 按位或 var1|var2 位运算符将其操作数看作一个二进制位的集合,各二进制位的取值只能是 0 和 1 中的一 个。通过位运算,程序员可以对某个数据中的特定二进制位进行检测或为给定的二进制位赋 值。 注意:位运算符的操作数只能是基本数据类型中的 char 和 int 类型及其各种变体而不支 持 float、double、void 或其他更复杂的数据类型。对于整型数据,由于符号位在不同位运算 符中的处理方法不同,且受到机器类型的影响。因此,为了保证程序运行的正确性,建议使 用 unsigned int 类型数据作为位运算符的操作数。 利用位运算符来设置及检测奇偶校验位,也可以用于简单的加密程序等。 8、sizeof 运算符 sizeof 运算符通知编译程序其操作数在内存中占用的字节数,它返回变量或括号中的类 型修饰符的字节长度。这是在程序编译时确定的,与程序的运行状态无关。其格式如下: sizeof(type_specifier); 或 sizeof(variable_name); 使用 sizeof 运算符的主要目的是为了增强程序的可移植性,使之不会由于机器表示同一 数据类型时存在字节长度不同而导致程序出错,从而确保程序可以在不同的硬件环境上正常 运行。 2.4.2 C++表达式 在 C++中,表达式是由运算符、常量、变量和表达式按照一定的语法规则组合而成的。 表达式在程序执行时完成一个或多个操作,并最终返回一个结果。若无特别说明,表达式的 返回结果是一个右值,其数据类型由参与运算的数据的数据类型来确定。 当不同数据类型的常量和变量在一个表达式中混合使用时,它们在计算时将被转换成同 一数据类型。通常 C++编译器在进行类型转换时遵循“向上转换”的原则,即将涉及数据的 数据类型转换为其中字长最长的数据类型。转换规则如下所示: (1)所有的 char 和 short int 都被转换为 int; (2)对所有的 float 被转换为 double; (3)对所有的操作数,若其中一个为 long double,则另一个也被转换为 long double; (4)否则,如果一个操作数为 double,则另一个也被转换为 double; (5)否则,如果一个操作数为 long,则另一个也被转换为 long; (6)否则,如果一个操作数为 unsigned,则另一个也被转换为 unsigned; 在按上述规则进行数据类型转换后,同一表达式中的操作数都变成了相同的数据类型数 据,而表达式的运算结果的数据类型也就是这些数据的数据类型。 当然,程序员也可以通过强制类型转换强迫表达式中的某些数据转换为某一特定的数据 类型。强制数据类型的形式如下所示: (type-specifier)variable (如:(double)var;)