C++笔记 --- 运算符
目录
(本章节中例子都是用 VS2005 编译调试的)
运算符
包括:
﹢(加), ‐(减), *(乘), ∕(除), ﹪(求模), ++i(自增), --i(自减), i++(自增),
i--(自减)
注意:
- 两个整型相除还为整型,两个负值除法求商中舍去方向一般 ' 向零取整 '
- 不同类型运算,统一成高精度后再运算
例子:
1 int a = 5; 2 int b = 3; 3 int c = 0; 4 5 c = a+b; //此时 c 的值为 8 6 c = a-b; //此时 c 的值为 2 7 c = a*b; //此时 c 的值为 15 8 c = a/b; //此时 c 的值为 1 9 c = a%b; //此时 c 的 值为 2 10 c = a ++; //此时 c 的 值为 5 11 c = a --; //此时 c 的值为 6 12 c = ++ a; //此时 c 的值为 6 13 c = -- a; //此时 c 的 值为 5
那么现在在对 i++,++i为例子(i--与--i同理)说明下他们的区别,由下面例子来说明
1 int c = 0, a = 0, b = 0; 2 3 c = ++a; // 此时 c 为1 4 c = a ; // 此时 c 为 1 5 //由此可以看到 c = ++a 的执行顺序好像是先执行 a 变量的自增 ,然后在执行 c = a 这个操作 6 //所以可以这么理解 ++a 表示的是,先把变量a自加,然后再执行++a所在的执行语句 7 8 c = b++; // 此时 c 为0 9 c = b; // 此时 c 为1 10 //由此可以看到 c = ++b 的执行顺序好像是先执行执行 c = b 这个操作 ,然后在执行 b 变量的自增操作 11 //所以可以这么理解 ++b 表示的是,先执行++a所在的执行语句,然后再执行把变量 b 自加这个操作
但是还有一个问题,要是一个语句中有多个 i++ 或者 ++i 呢?是执行多次自加还是只执行一次自加呢?让我们看看一个例子
1 // 例1 2 #include <iostream> 3 #include <cstdlib> 4 5 using namespace std; 6 7 void main() 8 { 9 int c = 0, a = 0, b = 0; 10 11 cout<<"两次次使用 ++a"<<endl; 12 c = (++a) + (++a); 13 cout<<"the value of c is "<<c<<endl; 14 c = a + a; 15 cout<<"the value of c is "<<c<<endl<<endl; 16 17 cout<<"两次次使用 b++"<<endl; 18 c = (b++) + (b++); 19 cout<<"the value of c is "<<c<<endl; 20 c = b + b; 21 cout<<"the value of c is "<<c<<endl<<endl; 22 23 a = 0;//先重新初始化下 变量a 24 cout<<"a++ 与 ++a 的混合使用, a++在前"<<endl; 25 c = (++a) + (a++); 26 cout<<"the value of c is "<<c<<endl; 27 c = a + a; 28 cout<<"the value of c is "<<c<<endl<<endl; 29 30 a = 0;//先重新初始化下 变量a 31 cout<<"a++ 与 ++a 的混合使用, a++在后"<<endl; 32 c = (a++) + (++a); 33 cout<<"the value of c is "<<c<<endl; 34 c = a + a; 35 cout<<"the value of c is "<<c<<endl<<endl; 36 37 a = 0;//先重新初始化下 变量a 38 cout<<"一个 a++ 与 两个 ++a 的混合使用"<<endl; 39 c = (a++) +(++a) + (++a); 40 cout<<"the value of c is "<<c<<endl; 41 c = a + a + a; 42 cout<<"the value of c is "<<c<<endl<<endl; 43 44 a = 0;//先重新初始化下 变量a 45 cout<<"两个 a++ 与 一个 ++a 的混合使用"<<endl; 46 c = (a++) + (a++) + (++a); 47 cout<<"the value of c is "<<c<<endl; 48 c = a + a + a; 49 cout<<"the value of c is "<<c<<endl<<endl; 50 51 system("pause"); 52 }
输出结果:
现在好像有点头绪了吧,让我们梳理下上面所说的内容:
-
- ++i 的执行流程好像就是把 i 的自增这个动作放到了执行语句的首部去执行,然后 i 自增这个动作结束后在回来执行 ++i 所在的执行语句
- i++ 的执行流程好像就是把 i 的自增这个动作放到了执行语句的尾部去执行,然后执行完 i++ 所在的执行语句后在回来执行 i 自增这个动作
- 按上面所说的我们在看看上面多个 i++ 和 ++i 组合产生的效果,执行语句先执行语句中的 ++i 让 i 自增n次(n便是在执行语句中 ++i 的次数),然后在执行 i++ 和 ++i 所在的执行语句,然后在执行 i++ 让 i 自增n次(n便是在执行语句中 i++ 的次数)
包括:
&&(与), ||(或), !(非)
注意:
最终会以bool值形式返回出来
例子:
1 // 例1 2 #include <iostream> 3 #include <cstdlib> 4 5 using namespace std; 6 7 void main() 8 { 9 bool a; 10 a = ( 5+10 == 15 ) && ( 5+10 == 5 ); 11 cout<<"a = ( 5+10 == 15 ) && ( 5+10 == 5 ) ? "<<a<<endl; 12 a = ( 5+10 == 15 ) || ( 5+10 == 5 ); 13 cout<<"a = ( 5+10 == 15 ) || ( 5+10 == 5 ) ? "<<a<<endl; 14 15 a = 0; 16 a = !a; 17 cout<<"a=0 !a= ? "<<a<<endl<<endl; 18 19 system("pause"); 20 } 21 22 /******************************************* 23 输出结果: 24 a = ( 5+10 == 15 ) && ( 5+10 == 5 ) ? 0 25 a = ( 5+10 == 15 ) || ( 5+10 == 5 ) ? 1 26 a=0 !a= ? 1 27 28 请按任意键继续. . . 29 ********************************************/
包括:
<(小于), <=(不大于), >(大于), >=(不小于), ==(等于), !=(不等于)
注意:
最终会以bool值形式返回出来
例子:
1 bool a = 0; 2 a = 5>10; //a = 0 3 a = 5<10; //a = 1 4 a = 5>=10; //a = 0 5 a = 5<=10; //a = 1 6 a = 5==10; //a = 0 7 a = 5!=10; //a = 1
包括:
~ (取反), &(位与), | (位或), ^ (位异或) , <<(左移) , >>(右移)
注意:
- 所有位运算的处理都是建立在数据的内容以2进制形式
- 左移形式:number<<n,将操作数number左移n位,丢弃移出位,以0填充
例子:
1 unsigned double b = 0xffffffff,c = 0x0000ffff; 2 3 cout<<hex;//把输出改为十六进制 4 5 cout<<"the value of b is "<<b<<endl; 6 cout<<"the value of c is "<<c<<endl<<endl; 7 8 cout<<"c & b then "<<(c&b)<<endl; 9 cout<<"c | b then "<<(c|b)<<endl; 10 cout<<"c ^ b then "<<(c^b)<<endl; 11 cout<<"~c then "<<~c<<endl; 12 cout<<"c<<4 then "<<(c<<4)<<endl; 13 cout<<"c>>4 then "<<(c>>4)<<endl;
输出结果:
包括:
+=(加x等于), -=(减x等于), *=(乘x等于), %=(除x取模等于), /=(除x等于),
>>=(向右移n位等于), <<=(向右移n位等于), &=(与x与位等于), ^=(与x异或位等于),
|=(与x或位等于)
解释:
我们以 += 为例,其他的也都一样,那么我们来看下面这个例子
1 int a = 0; 2 a += 1; //此时 a 的值为 1, 其实这个就等价于 a = a +1; 3 a += 5+9; //此时 a 的值为 15 , 道理同上,只是现在的 = 号的右边换成了表达式而已,也就是等价于 a = a + (5+9)
说明:
对对变量赋值,格式为 变量名 = 表达式 or 常量 or 变量 or 有返回值的函数调用;
例子:
1 // 例1 --- 2 int max(int a; int b) 3 { 4 return a>b?a:b; 5 } 6 void main() 7 { 8 int a, b, c, d; 9 a = 0xff8; //用常量赋值给变量, 十六进制赋值, 十进制表示为 4008,所以 a 值为 4008 10 b = a; //用变量赋值给变量,所以 b 值为 a 值为 4008 11 c = a+b; //用表达式赋值给变量,所以 c 值为 a 值加上 b 值为 8016 12 d = max(a,c); //用函数返回值赋值给变量,所以 d 值为 8016 13 } 14 15 // 例2 --- 16 unsigned char a; 17 a = 0xff8; //在变量赋值时候,若左边的值大于变量的所能存放的容量时候,会截取后半段,舍弃超出存储界限的前半段,所以此时 a 为 0xf8
sizeof与typedef
---sizeof---------------------------
用法:
- sizeof(object变量名 / 常量)
- sizeof (typename类型名 )
说明:
- sizeof(object变量名 / 常量)括号可加可不加,此时变量名,常量被解析成相对应的类型,返回类型占得内存字节数
- sizeof(typename类型名) 例如 sizeof(int)括号必须有,返回类型占得内存字节数
例子:
1 // 例子 -- 2 void main() 3 { 4 int ia; 5 short sa; 6 7 cout<<"整型变量的占用内存空间为: "<<sizeof(ia)<<" 字节"<<endl; 8 cout<<"短整型变量的占用内存空间为: "<<sizeof(short)<<" 字节"<<endl; 9 } 10 /******************************** 11 整型变量的占用内存空间为: 4 12 短整型变量的占用内存空间为: 2 13 ********************************/
---typedef--------------------------
用途:
定义类型的同义词 <不是简单的宏替换>
格式:
- typedef 类型 自定义名;
此时声明变量时候可有两种方法:(1)类型 变量名;(2)自定义名 变量名; - typedef* 类型 自定义名;
此时声明指针时候可有两种方法:(1)类型* 指针变量名;(2)自定义名 指针变量名; - typedef 返回类型 (*自定义名)();
此时声明函数指针的时候可有两种方法:(1)类型 (*函数指针名) ();(2)自定义名 函数指针名;
陷阱:
- typedef在语法上是一个存储类型的关键字(与auto一样)虽然它并不影响对象的存储性质,但不能与auto,static,register,extern,mutable连用
- typedef定义了一个类型的新别名,比如typedef char*PSTR,然后 int mystrcmp(const RSTR)const在这里给予了char*整个const的属性,所以const RSTR在这里为char* const
目的:
- 为了隐藏特定类型,强调使用类型的目的
- 允许一个类型有多个别名,使类型使用时目的明确易懂,跃过平台无关类型的限制
- 简化结构体名<例:typedef struct tagPOINT{int x,y} Point;Point p1>
- 为复杂的声明定义一个简单的别名
--------------------------------------------------------------------------------------------------------------
例子:
1 typedef int heigh; //以后就可以用 heigh 来定义 int 类型 变量 2 heigh i; //等价于 int i
来看个更复杂的例子:
1 typedef int*(*pfuc)(int ,char*); //以后可以用 pfuc 来定义函数指针 2 pfuc a; //等价于函数指针定义 int*(*a)(int,char *)
new与delete
---new--------------------------
形式:
- 结构 typename *point_name=new typename
- (解释: typename *point_name为声明指针类型名,new typename声明分配空间类型)
- 类 typename *point_name=new typename(构造函数参数表)
- (解释:typename *point_name声明指针类型名,new typename(构造函数参数表)声明分配空间类型)
- 数组 typename *point_name=new typename[]
- (解释:typename *point_name声明指针类型名,new typename[]声明分配空间类型)
说明:
由于point_name为地址,new动态生成的结构体无名称,不能用*point_name . 成员名来访问成员,但由于()优先级高,所以可以用(*point_name). 成员名来访问或用point_name -> 成员名
例子:
用new开辟变量,数组,类的例子
1 // 例1 -- 开辟变量 2 int *a = new int(0); //开辟变量并初始化变量为0,当然也可以开辟不初始的变量如: int *a = new int 3 4 //例2 -- 开辟数组 5 int *a = new int[5]; //开辟数组,数组长度为5 6 7 //例3 -- 开辟类实例 8 class A 9 { 10 int a ; 11 }; 12 void main () 13 { 14 A* a = new A(); //如果有构造函数有参数在括号中传递参数,如果有默认构造函数(即无参数的构造函数)括号可加可不加 15 }
用new开辟的类调用其成员函数或成员的例子
1 class A 2 { 3 public: 4 void show(){cout<<"hello!"}<<endl; 5 }; 6 void main() 7 { 8 A* a = new A; 9 a->show(); 10 (*a).show(); 11 }
---delete-------------------------
形式:
- 变量 delete point_name
- 数组 delete []point_name
例子:
1 class A 2 { 3 public: 4 void show(){cout<<"hello!"}<<endl; 5 }; 6 void main() 7 { 8 int *a = new int(0); 9 int *b = new int[5]; 10 A* c = new A; 11 12 delete a; //释放指针 a 指向的用new开辟出的变量内存 13 delete[] b; //释放指针 b 指向的用new开辟出来的数组的内存 14 delete c; //释放指针 c 指向的用new开辟出来的类的实例的内存 15 }
---new与delete使用说明----------
- 用new生成的变量/结构体/[]point_name(数组)用delete来释放
- delete释放的都是new指针指向的内存,而不会删掉指针本身
- 用new或new val[]分配的内存由delete或delete[]val来释放
- 对空指针应用delete是安全的
- 不能用sizeof操作符来确定动态分配数组包含的字节数
- new与delete必须互相兼容,new与delete,new[ ]与delete[ ]
C++操作符的优先级
操作符及其结合性 |
功能 |
用法 |
|
L |
:: |
全局作用域 |
::name |
L |
. |
成员选择 |
object.member |
R |
++ |
后自增操作 |
lvalue++ |
R |
sizeof |
对象的大小 |
sizeof expr |
L |
->* |
指向成员操作的指针 |
ptr->*ptr_to_member |
L |
* |
乘法 |
expr * expr |
L |
+ |
加法 |
expr + expr |
L |
<< |
位左移 |
expr << expr |
L |
< |
小于 |
expr < expr |
L |
== |
相等 |
Expr == expr |
R |
& |
位与 |
Expr & expr |
R |
^ |
位异或 |
Expr ^ expr |
R |
| |
位或 |
Expr | expr |
R |
&& |
逻辑与 |
Expr && expr |
R |
|| |
逻辑或 |
Expr || expr |
R |
?: |
条件操作 |
Expr ? expr : expr |
R |
= |
赋值操作 |
Lvalue= expr |
R |
throw |
抛出异常 |
Throw expr |
L |
, |
逗号 |
Expr, expr |
前缀递增/递减与解除引用优先级相同;后缀递增/递减高于解除引用 |