C++表达式(From:C++Primer)

4.1 算术运算符

*     两个整数相除的结果是整数。如果商含有小数部分,将被截掉。

*     %该操作符只能被应用在整数类型(charshortintlong)当两个操作数都是正数时,结果为正。但是,如果有一个(或两个)操作数为负,余数的符号则取决于机器。因此,移植性无法保证。

*     算术异常:算术表达式的计算会导致不正确或未定义的值。例如:除零、溢出。

*     标准C++头文件limits提供了与内置类型表示有关的信息,另外C++编译系统也提供了标准C头文件climitscfloat,它们定义了提供类似处理的预处理宏。如何使用这些头文件来防止溢出和下溢,参见[PLAUGER92]的第4章和第5章。

*     浮点数的算术符还涉及精度的问题:在计算机中,当它表示一个数值时,只有固定的数位可以使用。浮点数加法、乘法和减法的结果精度受到底层数据类型的固有精度的影响。

4.2 等于、关系和逻辑操作符

*     二元关系操作符(小于或等于操作符)的缺点①:左右操作数的计算顺序在标准CC++都是未定义的,因此计算过程必须是与顺序无关的。

*     缺点②:要判断ivaljvalkval是否各不相同。if ( ival != jval != kval )是错的,需要写成如下,if ( ival != jval && ival != kval && jval != kval )

4.3 赋值操作符

*     赋值和初始化都使用=一个对象只能被初始化一次,也就是在被定义的时候,但在程序中可以被赋值多次。

*     将不同类型的表达式赋值给一个对象时,右边表达式的类型必须与左边被赋值对象的类型完全匹配。编译器会试着隐式地将右操作数的类型转换成被赋值对象的类型,如果转换是合法的,则编译器会悄悄地进行(如果会引起精度损失,通常会给出一个警告)。如果不可能进行隐式的类型转换,那么赋值操作被标记为编译时错误。

*     赋值操作符的左操作数必须是左值——必须由一个相关联的、可写的地址值

4.4 递增和递减操作符

*     使用断言#include <cassert>assert(条件表达式)

4.5 条件操作符

*     语法格式:expr1 ? expr2 : expr3

4.6 sizeof操作符

*     sizeof的作用是返回一个对象或类型名的字节长度

       三种形式:①sizeof(type_name) sizeof(object) sizeof object

*     返回类型是size_t,这是一种与机器相关的typedef的定义。在<cstddef>中定义

*     sizeof应用在数组上,返回的是数组的字节长度,而不是数组的长度

*     sizeof在编译时刻计算,因此被看做常量表达式

4.7 newdelete表达式

*     没有语法能为动态分配的数组的元素指定一个显示的初始集合,如果是类的对象数组,如果定义了缺省构造函数,那么每一个元素都会使用缺省构造函数初始化。

*     将同一个对象释放一次以上是不合法的,会在运行时产生一个未定义的行为

4.9 逗号运算符

*     从左向右计算,结果是最右边的值

4.10 位操作符

*     如果一个对象被用作一组位或位域的离散集合,称此对象为位向量(bitvector

*     位向量是用来记录一组项目或条件的是/否信息的紧缩方法

*     编译器中,类型声明的限定修饰符,如constvolatile,有时就存储在位向量中

*     iostream库用位向量表示格式状态,例如:输出的整数是以十进制、十六进制等

*     支持位向量的两种方式:

       ①使用内置整值来表示位向量,典型使用unsigned int

       ②标准库bitset类,支持位向量的类抽象

建议使用标准库的类抽象

*     用整值数据类型作为位向量时,类型可以是有符号的,也可以是无符号的,强烈建议使      用无符号类型。因为大多数的位操作中,符号位的处理是未定义的,因此在不同的实现    中符号位的处理可能会不同。在一个实现下可行的程序,在另一个实现有可能会失败。

*     按位非操作符(~):翻转操作数的每一位,每个1被设置为0,而每个0被设置为1

*     移位操作符(<<>>):将其左边操作数的位向左或向右移动某些位。操作数中移到外    面的位被丢弃。左移操作符(<<)从右边开始用0补空位。如果操作数是无符号数,则是右移操作符(>>)从左边开始插入0,否则的话,它或者插入符号位的拷贝,或者插入0,具体由实现定义。

*     按位与(&):如果两个操作数都含1,则结果是1。否则是0

*     按位异或(^):在每个位所在处,如果两个操作数只有一个含有1,则结果该位为1,否则为0

*     按位或(|):如果两个操作数有一个或者两个含有1,则结果为1,否则为0.

*     通过使用常数1移位,再进行位操作来设置或取消某个位的值。

4.11 bitset操作

*     要使用bitset类,必须包含相关的头文件。#include <bitset>

*     bitset三种声明方式:

-      缺省定义中,只需简单地指明位向量的长度。例如:bitset<32> bitvec;缺省情况,所有位都被初始化为0

-      传递一个无符号参数。例如:bitset<32> bitvec2(0xffff);

-      传递一个代表01的字符串。例如:string bitval(“1010”); bitset<32> bitvec4(bitval);

*     转换为字符串:bitvec3.to_string();

*     转换为unsigned longto_ulong();

4.12 优先级

*     优先级顺序:

       -      ::(全局域)、::(类域)、::(名字空间域)

       -      .(成员选择)

       -      ->(成员选择)

       -      [](下标)

       -      ()(函数调用)()(构造函数)

       -      ++(后置递增)

       -      --(后置递减)

       -      C++类型转换

       -      ++/--(前置递增、递减)

       -      ~/!/-/+(按位非、逻辑非、一元减、一元加)

       -      *(解引用)

       -      &(取地址)

       -      ()(类型转换)

       -      */%+-

       -      << >>

       -      比较 <<=>>===!=

       -      &^(异或)、|(按位或)、&&(逻辑与)、||(逻辑或)、

       -      ?:(条件运算符)、=(赋值)、复合赋值(*=/=

       -      throw

       -      ,(逗号运算符)

4.13 类型转换

*     C++并不是把不同类型的值加在一起,而是提供一组算术转换,以便在执行算术运算之前,将两个操作数转换成共同的类型。

*     转换规则:小类型总是被提升成大类型,以防止精度丢失。这些转换由编译器自动完成,无需程序员介入----称为隐式类型转换

*     doubleint的转换不支持舍入,需要编写程序来实现。

4.13_1 隐式类型转换

*     C++定义了一组内置类型对象之间的标准转换,在必要时它们被编译器隐式地应用到对象上。隐式类型转换发生在下列这些典型的情况:

-      在混合类型的算术表达式中。这种情况下,最宽的数据类型成为目标转换类型称为算术转换

-      用一种类型的表达式赋值给另一种类型的对象,这种情况,目标转换类型是被赋值对象的类型

-      把表达式传递给一个函数调用,表达式的类型与形式参数的类型不相同。这种情况,目标转换类型是形式参数的类型

-      从一个函数返回一个表达式,表达式的类型与返回类型不相同。这种情况下,目标转换类型是函数的返回类型

4.13_2 算术转换

*     算术转换保证了二元操作符(如加法或乘法)的两个操作数被提升为共同的类型,然后再用它表示结果的类型。

*     为了防止精度丢失,如果必要的话,类型总是被提升为较宽的类型

*     所有含有小于整型的有序类型的算术表达式。在计算之前,其类型都会转换成整型。对于比int小的整型,包括:charsigned charunsgined charshortunsgined short,如果类型的所有可能的值都能包容在int内,它们就会被提升为int型,否则它们将被提升为unsgined int

*     long类型的一般转换有一个例外:如果一个操作数是long类型,另一个是unsigned int类型,只有机器上的long类型足够长以便能够存放unsigned int的所有值时,unsigned int才会转换为long,否则两个操作数都被提升为unsigned long

4.13_3 显示转换

*     也被成为强制类型转换(cast

*     static_castdynamic_castconst_castreinterpret_cast

*     const_cast,去掉表达式的常量性(以及volatile对象的volatile性)

*     static_cast,类似于C风格的强制转换。无条件转换、静态类型转换。编译器隐式执行的任何类型转换都可以由static_cast完成。用于:

       -      基类和子类之间的转换

       -      基本数据类型转换

       -      把空指针转换成目标类型的指针

       -      把任何类型的表达式转换成void类型

       -      static_cast不能去掉constvolatile属性

*     reinterpret_cast----转换为不同类型(不安全)时候使用。例如:

       double dval = 0.123;int *pi = reinterpret_cast<int*>(&dval);

4.13_4 旧式强制类型转换

*     只有当为C语言或标准C++之前的编译器编写代码的时候用这个语法

*     两种形式:

       -      type(expr)     // C++强制转换符号

       -      (type)expr     // C强制转换符号

*     对旧式强制转换符号的支持是为了对“在标准C++之前写的程序”保持向后兼容性,以及提供与C语言兼容的符号

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值