C++基础知识(四)—— 操作符/运算符

前面已经学习了变量和常量,我们可以开始对它们进行操作,这就要用到C++的操作符。有些语言,很多操作符都是一些关键字, 比如add, equals等等。C++的操作符主要是由符号组成的。这些符号不在字母表中,但是在所有键盘上都可以找到。这个特点使得C++程序更简洁,也更国际化。运算符是C++语言的基础,所以非常重要。

你不需要背下所有这一小节的内容,这些细节知识仅供你以后需要时参考 。

赋值Assignation (=)

赋值运算符的功能是将一个值赋给一个变量。

a = 5;

将整数5赋给变量a。= 运算符左边的部分叫做lvalue (left value),右边的部分叫做rvalue (right value)。lvalue 必须是一个变量,而右边的部分可以是一个常量,一个变量,一个运算(operation)的结果或是前面几项的任意组合。

有必要强调赋值运算符永远是将右边的值赋给左边,永远不会反过来。

a = b;

将变量b (rvalue)的值赋给变量a (lvalue),不论a当时存储的是什么值。同时考虑到我们只是将b的数值赋给a,以后如果b的值改变了并不会影响到a的值.

例如:如果我们使用以下代码(变量值的变化显示在绿色注释部分):

// 赋值符号例子

#include <iostream>
using namespace std;

int main ()
{
  int a, b;         // a:?,  b:?
  a = 10;           // a:10, b:?
  b = 4;            // a:10, b:4
  a = b;            // a:4,  b:4
  b = 7;            // a:4,  b:7

  cout << "a:";
  cout << a;
  cout << " b:";
  cout << b;

  return 0;
}
a:4 b:7               

以上代码结果是a的值为4, b的值为7。最后一行中b的值被改变并不会影响到a,虽然在此之前我们声明了a = b; (从右到左规则right-to-left rule)。

C++拥有而其他语言没有的一个特性是赋值符 (=) 可以被用作另一个赋值符的rvalue (或rvalue的一部分) 。例如:

a = 2 + (b = 5);

等同于:

b = 5;

a = 2 + b;

它的意思是:先将5赋给变量b,然后把前面对b的赋值运算的结果(即5)加上2再赋给变量a,这样最后a中的值为7。因此,下面的表达式在C++中也是正确的:

a = b = c = 5; //将5同时赋给3个变量a, b和c。

数学运算符Arithmetic operators ( +, -, *, /, % )

C++语言支持的5种数学运算符为:

  • + 加addition
  • - 减subtraction
  • * 乘multiplication
  • / 除division
  • % 取模module

加减乘除运算想必大家都很了解,它们和一般的数学运算符没有区别。

唯一你可能不太熟悉的是用百分号(%)表示的取模运算(module)。取模运算是取两个整数相除的余数。例如,如果我们写a = 11 % 3;,变量a的值将会为结果2,因为2是11除以3的余数。

组合运算符Compound assignation operators (+=, -=, *=, /=, %=, >>=, <<=, &=, ^=, |=)

C++以书写简练著称的一大特色就是这些组合运算符compound assignation operators (+=, -=, *= 和 /= 及其他) ,这些运算符使得只用一个基本运算符就可改写变量的值:

value += increase; 等同于 value = value + increase;

a -= 5; 等同于 a = a - 5;

a /= b; 等同于 a = a / b;

price *= units + 1; 等同于 price = price * (units + 1);

其他运算符以此类推。例如:

// 组合运算符例子

#include <iostream>
using namespace std;

int main ()
{
  int a, b=3;
  a = b;
  a+=2;             // 相当于 a=a+2
  cout << a;
  return 0;
}
5                  

递增和递减Increase and decrease

书写简练的另一个例子是递增(increase)运算符 (++)和递减(decrease) 运算符(--)。它们使得变量中存储的值加1或减1。它们分别等同于+=1和-=1。因此:

a++;

a+=1;

a=a+1;

在功能上全部等同,即全部使得变量a的值加1。

它的存在是因为最早的C编译器将以上三种表达式的编译成不同的机器代码,不同的机器代码运行速度不一样。现在,编译器已经基本自动实行代码优化,所以以上三种不同的表达方式编译成的机器代码在实际运行上已基本相同。

这个运算符的一个特点是它既可以被用作prefix前缀,也可以被用作后缀suffix,也就是说它既可以被写在变量标识的前面(++a),也可以被写在后面(a++)。虽然在简单表达式如a++或++a中,这两种写法代表同样的意思,但当递增increase或递减decrease的运算结果被直接用在其它的运算式中时,它们就代表非常不同的意思了:当递增运算符被用作前缀prefix (++a) 时,变量a的值线增加,然后再计算整个表达式的值,因此增加后的值被用在了表达式的计算中;当它被用作后缀suffix (a++)时,变量a的值在表达式计算后才增加,因此a在增加前所存储的值被用在了表达式的计算中。注意以下两个例子的不同:

例 1 例 2
B=3;

A=++B;

// A 的值为 4, B 的值为 4

B=3;

A=B++;

// A 的值为 3, B 的值为 4

在第一个例子中,B在它的值被赋给A之前增加1。而在第二个例子中B原来的值3被赋给 A然后B的值才加1变为4。

关系运算符Relational operators ( ==, !=, >, <, >=, <= )

我们用关系运算符来比较两个表达式。如ANSI-C++ 标准中指出的,关系预算的结果是一个bool值,根据运算结果的不同,它的值只能是真truefalse

例如我们想通过比较两个表达式来看它们是否相等或一个值是否比另一个的值大。以下为C++的关系运算符:

== 相等Equal
!= 不等Different
> 大于Greater than
< 小于Less than
>= 大于等于Greater or equal than
<= 小于等于Less or equal than

下面你可以看到一些实际的例子:

(7 == 5) 将返回false.
(5 > 4) 将返回true.
(3 != 2) 将返回true.
(6 >= 6) 将返回true.
(5 < 5) 将返回false.

当然,除了使用数字常量,我们也可以使用任何有效表达式,包括变量。假设有a=2, b=3和c=6,

(a == 5) 将返回false.
(a*b >= c) 将返回true 因为它实际是(2*3 >= 6)
(b+4 > a*c) 将返回false因为它实际是(3+4 > 2*6)
((b=2) == a) 将返回true.

注意:运算符= (单个等号)不同于运算符== (双等号)。第一个是赋值运算符(将等号右边的表达式值赋给左边的变量);第二个(==)是一个判断等于的关系运算符,用来判断运算符两边的表达式是否相等。因此在上面例子中最后一个表达式((b=2) == a),我们首先将数值2赋给变量b,然后把它和变量a进行比较。因为变量a中存储的也是数值2,所以整个运算的结果为true。

在ANSI-C++标准出现之前的许多编译器中,就像C语言中,关系运算并不返回值为真true或假falsebool值,而是返回一个整型数值最为结果,它的数值可以为0,代表"false"或一个非0数值(通常为1)来代表"true"。

逻辑运算符Logic operators ( !, &&, || )

运算符 ! 等同于boolean 运算NOT (取非),它只有一个操作数(operand),写在它的右边。它做的唯一工作就是取该操作数的反面值,也就是说如果操作数值为真true,那么运算后值变为假false,如果操作数值为假false,则运算结果为真true。它就好像是说取与操作数相反的值。例如:

!(5 == 5) 返回false,因为它右边的表达式(5 == 5)为真true.
!(6 <= 4) 返回true因为(6 <= 4)为假false.
!true 返回假false.
!false 返回真true.

逻辑运算符&&和||是用来计算两个表达式而获得一个结果值。它们分别对应逻辑运算中的与运算AND 和或运算OR。它们的运算结果取决于两个操作数(operand)的关系:

第一个操作数

a

第二个操作数

b

结果

a && b

结果

a || b

true true true true
true false false true
false true false true
false false false false

例如 :

( (5 == 5) && (3 > 6) ) 返回false ( true && false ).

( (5 == 5) || (3 > 6)) 返回true ( true || false ).

条件运算符Conditional operator ( ? )

条件运算符计算一个表达式的值并根据表达式的计算结果为真true或假false而返回不同值。它的格式是:

condition ? result1 : result2 (条件?返回值1:返回值2)

如果条件condition 为真true,整个表达式将返回esult1,否则将返回result2。

7==5 ? 4 : 3 返回3,因为7不等于5.
7==5+2 ? 4 : 3 返回4,因为7等于5+2.
5>3 ? a : b 返回a,因为5大于3.
a>b ? a : b 返回较大值,a 或b.
// 条件运算符例子

#include <iostream>
using namespace std;

int main ()
{
  int a,b,c;

  a=2;
  b=7;
  c = (a>b) ? a : b;

  cout << c;

  return 0;
}
7                  

上面的例子中a的值为2,b的值为7,所以表达式(a>b)运算值为假(false),所以整个表达式(a>b)?a:b要取分号后面的值,也就是b的值7。因此最后输出 c 的值为7。

逗号运算符 ( , )

逗号运算符 (,) 用来分开多个表达式,并只取最右边的表达式的值返回。

例如有以下代码:

a = (b=3, b+2);

这行代码首先将3赋值给变量b,然后将 b+2 赋值给变量 a。所以最后变量a 的值为5,而变量b的值为3

位运算符Bitwise Operators ( &, |, ^, ~, <<, >> )

位运算符以比特位改写变量存储的数值,也就是改写变量值的二进制表示:

op asm Description
& AND 逻辑与 Logic AND
| OR 逻辑或Logic OR
^ XOR 逻辑异或Logical exclusive OR
~ NOT 对1取补(位反转)Complement to one (bit inversion)
<< SHL 左移Shift Left
>> SHR 右移Shift Right

变量类型转换运算符Explicit type casting operators

变量类型转换运算符可以将一种类型的数据转换为另一种类型的数据。在写C++中有几种方法可以实现这种操作,最常用的一种,也是与C兼容的一种,是在原转换的表达式前面加用括号()括起的新数据类型:

int i;

float f = 3.14;

i = (int) f;

以上代码将浮点型数字3.14转换成一个整数值(3)。这里类型转换操作符为(int)。在C++中实现这一操作的另一种方法是使用构造函数constructor 的形式:在要转换的表达式前加变量类型并将表达式括在括号中:

i = int ( f );

以上两种类型转换的方法在C++中都是合法的。另外ANSI-C++针对面向对象编程(object oriented programming)增加了新的类型转换操作符 (参考Section
5.4, Advanced class type-casting
).

sizeof()

这个运算符接受一个输入参数,该参数可以是一个变量类型或一个变量自己,返回该变量类型(variable type) 或对象(object)所占的字节数:

a = sizeof (char);

这将会返回1给a,因为char是一个常为1个字节的变量类型。

sizeof返回的值是一个常数,因此它总是在程序执行前就被固定了。

其它运算符

在本教程后面的章节里我们将看到更多的运算符,比如指向指针的运算或面向对象编程特有的运算,等等,我们会在它们各自的章节里进行详细讨论。

运算符的优先度 Precedence of operators

当多个操作数组成复杂的表达式时,我们可能会疑惑哪个运算先被计算,哪个后被计算。例如以下表达式:

a = 5 + 7 % 2

我们可以怀疑它实际上表示:

a = 5 + (7 % 2) 结果为6,还是 a = (5 + 7) % 2 结果为0?

正确答案为第一个,结果为6。每一个运算符有一个固定的优先级,不仅对数学运算符(我们可能在学习数学的时候已经很了解它们的优先顺序了),所有在C++中出现的运算符都有优先级。从最从最高级到最低级,运算的优先级按下表排列:

优先级

Level

操作符

Operator

说明

Description

结合方向

Grouping

1 :: 范围 从左到右
2 () [] . -> ++ -- dynamic_cast static_cast reinterpret_cast const_cast typeid 后缀 从左到右
3 ++ -- ~ ! sizeof new delete 一元(前缀) 从右到左
* & 指针和取地址
+ - 一元符号
4 (type) 类型转换  从右到左
5 .* ->* 指向成员的指针 从左到右
6 * / % 乘、除、取模 从左到右
7 + - 加减 从左到右
8 << >> 位移 从左到右
9 < > <= >= 关系操作符 从左到右
10 == != 等于、不等于 从左到右
11 & 按位与运算 从左到右
12 ^ 按位异或运算 从左到右
13 | 按位或运算 从左到右
14 && 逻辑与运算 从左到右
15 || 逻辑或运算 从左到右
16 ?: 条件运算 从右到左
17 = *= /= %= += -= >>= <<= &= ^= |= 赋值运算 从右到左
18 , 逗号 从左到右

结合方向Grouping定义了当有同优先级的多个运算符在一起时,哪一个必须被首先运算,最右边的还是最左边的。

所有这些运算符的优先级顺序可以通过使用括号parenthesis signs (和)来控制,而且更易读懂,例如以下例子:

a = 5 + 7 % 2;

根据我们想要实现的计算的不同,可以写成:

a = 5 + (7 % 2); 或者

a = (5 + 7) % 2;

所以如果你想写一个复杂的表达式而不敢肯定各个运算的执行顺序,那么就加上括号。这样还可以使代码更易读懂。

时间: 2024-10-06 00:45:04

C++基础知识(四)—— 操作符/运算符的相关文章

C# 基础知识 (四).C#简介及托管代码

        暑假转瞬即逝,从10天的支教生活到1周的江浙沪旅游,在这个漫长的暑假中我经历了很多东西,也学到了很多东西,也认识到了很多不足之处!闲暇之余我准备重新进一步巩固C#相关知识,包括C#入门知识.C#并行开发.ASP网站等.这篇文章我介绍的是书籍--C#入门经典(Beginning C#) 作者Karli Watson.主要包括的是我自己缺乏的一些C#简介知识和托管代码的内容.内容比较简单,参照该书籍较多,相当于自己的在线笔记!                             

Python基础知识(四)

Python基础知识(四) 一丶列表 定义格式: 是一个容器,由 [ ]表示,元素与元素之间用逗号隔开. 如:name=["张三","李四"] 作用: 存储任意类型的数据 (32位机器能存5亿多,64为机器存储更多) 特点: 可变 (增,删,改,查) 默认从左到右 ,从0开始 . 有序(索引,切片,步长) 操作: 增 , 删 , 改 ,查 ,索引,切片,步长 ?? #列表的两种定义方式 name=["香蕉","西瓜",&quo

PHP学习笔记(四)--基础知识之常用运算符

原文地址:http://blog.51cto.com/dezhou/2061462

基础知识1.0运算符

C#是微软公司在2000年7月发布的一种全新且简单.安全.面向对象的程序设计语言,是专门为.net的应用而开发的语言.它吸收了C++.VB.Delphi.java等语言的优点,体现了当今最新的程序设计技术的功能和精华.其特点有: 1.语言简洁. 2.保留了C++的强大功能. 3.快速应用开发功能. 4.语言的自由性. 5.强大的WEB服务器控件. 6.支持跨平台. 7.与XML相融合. 运算符:一.算术运算符:+ - * /% ——取余运算取余运算的应用场景:1.奇偶数的区分.2.把数变化到某个

计算机科学基础知识(四)动态库和位置无关代码

一.前言 本文主要描述了动态库以及和动态库有紧密联系的位置无关代码的相关资讯.首先介绍了动态库和位置无关代码的源由,了解这些背景知识有助于理解和学习动态库.随后,我们通过加-fPIC和不加这个编译选项分别编译出两个relocatable object file,看看编译器是如何生成位置无关代码的.最后,我们自己动手编写一个简单的动态库,并解析了一些symbol Visibility.动态符号表等一些相关基本概念. 本文中的描述是基于ARM MCU,GNU/linux平台而言的,本文是个人对动态库

KnockoutJS基础知识(四)

几乎所有Web应用程序都要和服务器端交换数据,交换数据时最方便的就是使用JSON格式.Knockout可以实现很复杂的客户端交互,对于前后端交互使用的技术最为基本且常用的是Ajax,本次利用Ajax和ko的双向绑定完成一些简单的功能,可以快速展示出ko的方便之处. Demo地址: https://gitee.com/530521314/koInstance.git 一.服务端返回数据绑定到客户端 1.准备好一些初始数据,直接通过View方法将视图实体返回到视图文件中. 2.前端设置为强类型,初始

JS基础(四)运算符

一.比较运算符 1.== : 判断两边值是否相等 2.>= : 判断左边的值是否大于或等于右边的值 3.<= : 判断左边边的值是否小于或等于右边的值 4.>   : 判断左边的值是否大于右边的值 5.<   : 判断右边的值是否大于左边的值 6.!=  : 判断两边的值是否不相等 7.===: 判断两边的值是否绝对相等 8.!==: 判断两边的值是否绝对不相等(绝对相等或绝对不相等,判断除了值以外还需要判断数据类型) 二.逻辑运算符 1.&&:逻辑与,两边的结果必

python 基础知识四、字典

常见字典常量和操作 操作 解释 D = {} 空字典 D = {'spam':2 , 'egg':3} 两项目字典 D = {'food':{'ham':1,'egg':2}} 嵌套 D = dict.fromkeys(['a','b']) 其他构造技术 D = dict(zip(keylist, valslist)) 关键之.对应的对.键列表 D = dict(name='bob', age=42) D['eggs'] 以键进行索引运算 'eggs' in D  成员关系:键存在测试 D.ke

Linux基础知识四

1.复制/etc/skel目录为/home/tuser1,要求/home/tuser1及其内部文件的属组和其它用户均没有任何访问权限. [[email protected] ~]# cp -a /etc/skel /home/tuser1/ [[email protected] ~]# chmod -R go-rwx /home/tuser1/ 2.编辑/etc/group文件,添加组hadoop. [[email protected] ~]# echo "hadoop:x:3007:"

HTML基础知识四

1.  内嵌入式框架 <iframe src="网页位置" width="宽度" height="高度"frameboeder="0/1(框架边框,0表示没有边框:1表示有边框)" scrolling="滚动条方式yes /  no  /auto(默认,当文字多余高度,自动显示滚动条)"> </iframe> 2.  滑动字幕:方向->方式->速度à延时à次数à鼠标à样式