C++语言程序设计教程|运算符
- 运算符
- 1. 优先级与结合性
- 2. 算术运算符
- 3. 关系运算符
- 4. 逻辑运算符
- 5. 位运算符
- 6. 赋值运算符
- 7 . ++、--运算符
- 8. 其它运算符
- 8.1. 条件运算符
- 8.2. 逗号运算符
- 8.3. 求字节运算符
- 8.4. 成员运算符
- 8.5. 取地址运算符
- 8.6. 取指针内容运算符
- 9. 运算符优先级的规律
运算符
运算符是描述对数据进行的运算(操作)、体现数据之间运算关系的符号,运算符也叫操作符。1
1. 优先级与结合性
优先级是指表达式中运算符运算的顺序。当一个表达式中包含多个运算符时,先进行优先级高的运算,再进行优先级低的运算。如果表达式中出现了多个相同优先级的运算,运算顺序就要看运算符的结合性了。
结合性是指操作数左右两边运算符的优先级相同时,优先和哪个运算符结合起来,进行运算。运算符的结合顺序有两种:左结合和右结合。
2. 算术运算符
- 算术运算符的意义、优先级与数学中一致:+(正号), -(负号)是一元运算,优先级高于二元运算,*、/、%优先级高于+(加)、-(减)运算。
//例如:
a=10; b=5; a+b*-1; //得到结果5
- %要求两个操作数的值必须是整数或字符型数。“操作数1%操作数2”计算结果是操作数1被操作数2除的余数。当两个操作数都是正数时,结果为正;如果有一个(或两个)操作数为负,余数的符号取决于机器。
21%6 //结果是3
4%2 //结果是0
21%-5 //机器相关:结果为-1或1
- 当/运算符用于两个整数相除时,如果商含有小数部分,将被截掉。如果要进行通常意义的除运算,则至少应保证除数或被除数中有一个是浮点数或双精度数。
5/4 //结果是1
4/5 //结果是0
5/4.0 //结果是1.25
4.0/5 //结果是0.8
- 在使用算术运算符时,需要注意有关算术表达式求值溢出的处理问题;
short i=32767,j,k;
j=i+1;
k=i+2;
cout<<"j="<<j <<", k="<<k<<endl; //执行结果为:j=-32768, k=-32767
3. 关系运算符
关系运算符及其含义:
- 若关系运算符的计算结果继续用在表达式中,true与false分别当成了1与0。
- 关系运算符的操作数可以是任何基本数据类型的数据,但由于实数(float)在计算机中只能近似地表示一个数,所以,一般不能直接进行比较。当需要对两个实数进行==、!=比较时,通常的做法是指定一个极小的精度值,若两实数的差在这个精度之内时,就认为两实数相等,否则为不等。
x==y //应写成fabs(x-y)<1e-6
x!=y //应写成fabs(x-y)>1e-6
//fabs(x)求double类型数x的绝对值
- 关系表达式就是由关系运算符将两个操作数连接起来的式子。这两个操作数可以为常量、变量、算术表达式等。
4. 逻辑运算符
逻辑运算符操作数类型为bool型,返回类型亦为bool型。
- 逻辑运算符的操作数为bool型,当为其它数据类型时,将它转换成bool值参加运算。
//设
a=10,b=5,c=-3
//则: !a的值为0;a&&b的值为1; a||b的值为1;
- C++对于二元运算符&&和||可进行短路求值(short-circuit evaluation)。由于&&与||表达式按从左到右的顺序进行计算,如果根据左边的计算结果能得到整个逻辑表达式的结果,右边的计算就不需要进行了,该规则叫短路求值。
//例如:
(num!=0)&&(1/num>0.5)
- 当表示的逻辑关系比较复杂时,用小括号将操作数括起来是一种比较好的方法。
5. 位运算符
位运算分为移位运算与按位逻辑运算
unsigned char c(135),d (43); //二进制表示分别为10000111和00101011。
- 运算符 ~ 将操作数逐位取反,即将原来为1的位变为0,原来为0的位变为1。例如,按位求反~c的结果为01111000。
- 运算符 &将两个操作数对应位逐一地进行逻辑与运算。与运算的规则为“见0则0”,即两个数中只要有一个为0,则其逻辑与的结果就为0。
- 运算符| 将两个操作数对应位逐一地进行逻辑或运算。逻辑或运算的规则为“见1则1”,即两个数中只要有一个为1,则其逻辑或的结果就为1。
- 运算符^ 将两个操作数对应位逐一地进行逻辑异或运算。逻辑异或运算的规则为“同则0,异则1”,即两个数只要不同,则其逻辑异或的结果就为1;否则为0。
- 运算符 << 将左操作数向左移动其右操作数所指定的位数,移出的位补以0。将一个数左移一位,相当将该数乘以2;左移两位,相当将该数乘以4。一般说来,将一个数左移n位,就相当将该数乘以2n。所以,在程序中,常用左移位来进行快速的乘法运算。
- >> 将左操作数向右移动其右操作数所要求的位数,移出的位补以0。将一个数右移n位,相当于将该数除以2n。这与整型和字符型数据的除法运算完全一致,所以在程序中常用右移位来进行快速的除法运算。
6. 赋值运算符
赋值运算符表
简单赋值运算符的使用格式:
左表达式= 右表达式
其功能是将右表达式(右操作数)的值放到左表达式表示的内存单元中,因此左表达式一般是变量或表示某个地址的表达式,称为左值,在运算中作为地址使用。右表达式在赋值运算中是取其值使用,称为右值。所有赋值运算左表达式都要求是左值。
复合赋值运算符的运算过程为:先将两个表达式做运算符所规定的算术或位运算,然后将运算的结果赋给左表达式。
左表达式@= 右表达式; ——》 左表达式=(左表达式@ 右表达式);
例如:
设a和b的值分别为2和6,复合赋值运算式b*=a+3的计算过程为:
①先计算复合赋值运算符的右表达式的值,即a+3的和,结果为5;
②然后,做复合赋值运算符所规定的算术运算,即求b与上述结果的乘积,结果为30;
③最后进行赋值运算,将上述运算结果赋给复合赋值运算符的左操作数b。同时,整个表 达式的值也为30。
关于赋值运算符的说明:
- 用赋值运算符=连接起来的表达式叫做赋值表达式。赋值表达式是C++语言(包括C语言)中所特有的,其它大多数语言中,只有赋值语句而没有赋值表达式这一语法要素。赋值表达式仍可作为操作数进行运算,赋值表达式的类型为左边变量的类型,其返回值为赋值后左边变量的值。
float x;
x=2.6; //返回值为2.6, 类型为float;
- 复合赋值运算符所表示的表达式不仅比一般赋值运算符表示的表达式简练,而且所生成的目标代码也较少,因此,C++语言程序中应尽量采用复合赋值运算符的形式表示。
- 在C++中还可以连续赋值,赋值运算符具有右结合性.
x=y= 2.6; // 它相当于:x=(y=2.6);
a=b=3+8; //先做3+8,然后将11赋给b,再将b的值11赋给a。
c=b*=a+3; //运算分解为①a+3 ②b=b*(a+3) ③c=b
7 . ++、–运算符
这两个运算符都前置和后置两种形式。所谓前置是指运算符在操作数的前面,后置是指运算符在操作数的后面。
//例如:
i++; //++后置
--j; //--前置
- 都是使操作数的值增1或减1,但对表达式的值的影响却完全不同。前缀运算是先变化后运算,后缀运算是先运算后变化。
//前置形式
int i=5; x=++i; y=i; // i 先加1(增值)后再赋给x (i=6, x=6,y=6)
int i=5; ++i; x=y=i; // (i=6, y=6,x=6)
//后置形式
int i=5; x=i++; y=i; // i 赋给后再加1(x=5, i=6,y=6)
int i=5; i++; x=y=i; // (i=6, y=6,x=6)
- 由于++、–运算符内含了赋值运算,所以运算对象只能赋值,不能作用于常量和表达式。5++、(x+y)++都是不合法的。
8. 其它运算符
8.1. 条件运算符
条件运算符也称三目运算符, 是C++中唯一的一个三目运算符。格式为:
d1 ?d2:d3
其中,d1,d2和d3分别是三个表达式。该运算符的功能是:
①先计算d1;
②如果d1的值为true(非0),返回d2的值作为整个条件运算表达式的值;
③如果d1的值为false(0),返回d3的值作为为整个条件运算表达式的值。
条件运算表达式的返回类型将是d2和d3这两个表达式中类型高(表示的数值范围大)的那种类型。
例如:
a=(x>y ? 12 : 10.0); //若x>y(x>y的值为true), 将12赋给a; 否则a=10.0。条件运算表达式> 的返回类型为10.0的类型double。
x?y=a+10:y=3*a-1; //若x非0则把a+10的值赋给y,否则把3*a-1的值赋y
8.2. 逗号运算符
逗号可作分隔符使用,将若干变量隔开,如:int a,b,c;一般形式为:
表达式1,表达式2,……,表达式n;
逗号表达式的求解过程为:先求表达式1的值,再求表达式2的值……,最后求表达式n的值。整个逗号表达式结果的值是最后一个表达式n的值。它的类型也是最后一个表达式的类型。
例如:
a=a+b, b=b*c, c=c-a;
//设a=3,b=5,c=7,该表达式依次计算出a的值为8、b的值为35、c的值为-1、且整个表达式的值为-1。 更进一步:
x=(a=a+b, b=b*c, c=c-a) ; // x的值为-1。
逗号运算符还用在只允许出现一个表达式而又需要多个表达式才能完成运算的地方,用它将几个表达式连起来组成一个逗号表达式。
在C++语言所有运算符中,逗号表达式的优先级最低。
8.3. 求字节运算符
sizeof是C++语言的一种单目运算符,用来求得某种类型或某个变量所占字节数(长度)。
sizeof 运算符以int型形式给出了其操作数的存储空间大小。操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型决定。该运算符的使用形式如下:
sizeof (类型说明符|变量名|常量)
例: int a,b [10]; 在32位系统下,表达式sizeof(a)的值应该为4,与sizeof(int)的值相等;同样,sizeof (b)的值为40,它是数组b的所有元素所占的总内存字节数;
sizeof(3.1)的值为8,即双精度数的长度。 sizeof运算符返回值类型为size_t,在头文件stddef.h中定义,它是一个依赖于编译系统的值,一般定义为:
typedef unsigned int size_t;
8.4. 成员运算符
(1)下标运算符[ ]
(2) 取结构或联合变量成员运算符.
(3) 通过指针取结构或联合体成员运算符->
8.5. 取地址运算符
&运算符用来获取某个变量的内存单元地址值,格式如下:
&变量名
例如: int a; &a表示取变量a的地址值,即是变量a在内存中被分配的内存地址值。
8.6. 取指针内容运算符
取指针内容运算符*是一个单目运算符,用来间接地获取某指针变量指向内存单元的值。
//例如:
int a=5; int *p=&a;
变量a标识的内存单元中存放的值为5,指针变量p指向变量a,将该运算符作用于p(即*p),表示取p指向的内存单元的内容,p指向的内存单元为变量a。因此,*p取出a存放于内存单元的值5。
该运算符是用来改变原来的优先级的,括号运算符的优先级最高。括号运算符可以包含使用(即嵌套),即在括号内还可以使用括号,在出现多重括号时,应该先作最内层括号,按从里向外的顺序进行。
9. 运算符优先级的规律
(1) 运算符的优先级按单目、双目、三目、赋值依次降低。
- 单目运算是右结合的,旨在与右边的数结合在一起形成一个整体,因此优先级高。
- 算术运算中的+(正)
、-(负)、++、–、逻辑运算中的取非!, 按位运算中的取反~从各类运算中提取到单目运算中。
赋值运算之所以优先级低且为右结合,是因为要右边的表达式计算完后才赋值给左边的变量。
(2) 算术、移位、关系、按位、逻辑运算的优先级依次降低。
- 移位运算是一种高效的算术运算,看作算术运算的补充,优先级在算术运算后。
- 算术运算后的结果要进行比较,因此关系运算的优先级在算术、移位后。
- 关系运算得出的逻辑值要进行运算,所以逻辑运算优先级在关系运算后。
- 关系运算得出的逻辑值要进行运算,所以逻辑运算优先级在关系运算后。
本教程仅供教学使用,参考教材 :《C++语言程序设计教程》,杨进才、沈显君编著,清华大学出版社,2022年1月第4版 ↩︎