C++Primer_学习笔记(六)

本文深入探讨了C++中的逗号表达式、位操作符、bitset操作、操作符优先级、类型转换等核心概念。详细解析了算术转换规则,如何在不同数据类型间进行隐式类型转换,以及如何利用bitset简化位向量操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2019年4月22日

4.10 逗号操作符

逗号表达式是一系列由逗号分开的表达式。这些表达式从左向右计算。逗号表达式的结果是最右边表达式。

在下面例子中,条件操作符的每边都是逗号表达式。第一个逗号表达式的值是ix,而第二个表达式的值是0。

int main()

{

   //examplies of a comma expression

   //ia , sz ,and index are defined elsewhere

   int ival = (ia != 0)

       ? ix= get_value(),ia[index] = ix

       : ia = new int[sz] , ia[index] = 0;

}

   

    4.11 位操作符

    位操作符把操作数解释成有序的集合,这些位可能是独立的,也可能组成域(field)。每个位可以含有0(off)或1(on)。位操作符允许程序员设置或测试独立的位或位域。如果一个对象被用作一组位或位域的离散集合,那么这样的对象称为位向量(bitvector)。位向量是一种用来记录一组项目或条件的是/否信息[flag]的紧缩方法。例如,在编译器中,类型声明的限定修饰符(qualifier),如const和volatile,有时就被存储在位向量中。iostream库用位向量表示格式状态,例如输出的整数是以十进制、十六进制,还是八进制显示。

4.12 bitset操作

test(pos) pos位是否为1?

any()     任意位是否为1?

none()    是否没有位为1?

count()   值是1的位的个数

size()    位元素的个数

[pos]     访问pos位

flip()    翻转所有的位

flip(pos) 翻转pos位

set()     将所有位置1

set(pos)  将pos位置1

reset    将所有位置0

reset(pos)将pos位置0

 

用整数类型表示位向量的问题在于,使用位操作符来设置、复位和测试单独的位,层次也比较低,也比较复杂。例如,用整值类型将第27位设置为1,我们可以这些写: quiz1 |= 1<<27;

而用bitset来做,我们可以这样写:  quizl[27] = 1;

或者                                quiz1.set(27);

 

 

4.13优先级

    操作符优先级是指复合表达式中操作符计算的顺序。例如,在下面的定义中,最终被赋值给ival的是什么?

int ival = 6+3*4/2+2   //14

    用括号把一些子表达式起来,可以改变优先级。再复合表达式计算中,第一个动作是计算所有括号中的字表达,在用计算的结果代替每个子表达式,然后计算。里边的括号比外面的括号先计算。

 

4.14类型转换

    4.14.1隐式类型转换

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

·在混合类型的算术表达式中。在这种情况下,最宽的数据类型称为目标转换类型。这也称为算术转换(arithmetic conversion)。

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

int *pi = 0;

ival = dval;

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

extern double sqrt(double);

cout<<”The square root of 2 if”

       <<sqrt(2)<<endl;

 

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

double difference(int ival1 , int ival2)

{

    //返回值被提升为double类型

    return ival1 – ival2;

}

4.12.2 算术转换

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

  1. 为防止精度损失,如果必要的话,类型总是被提升为较宽的类型。
  2. 所有含有小于整型的有序类型的算术表达式。在计算之前,其类型都会都会被转换成整型。

规定的定义如下面所述,这些规则定义了一个类型转换层次结构。(我们从最宽的类型long double开始。)

如果一个操作数的类型是long double,那么另一个操作数无论是什么类型,都将被转换成long double。

    如果两个操作数都不是long double型,那么当其中一个操作数的类型是double型,则另一个就将被转换成double型。例如:   

int ival;

    float fval;

    doule davl;

    //在加法之前,fval和ival都被转换成double

    dval + fval + ival;

    类似地,如果两个操作数都不是double型,而其中一个操作数是float型,则另一个被转换成float型。例如:  

  char cval;

    int ival;

    float fval;

    //在计算加法前,ival和cval 都被转换成double

    cval + fval + ival;

    否则,因为两个操作数都不是三种浮点类型之一,它们一定是某种整值类型。在确定共同目标提升类型之前,编译器将在所有小于int 的整值类型上施加一个被称为整值提升(integral promotion)的过程。

   在进行整值提升时候,类型char、signed char 、unsigned char 和short int 都被提升为类型int 。

    如果机器上的m型足够表示所有的unsinned shoft型的值,则unsigned short int 也被转换成int。否则,它会被提升为unsigned int 。

    wchar_t 和枚举类型被提升为能够表示其底层类型(underlying type)所有值的最小整数类型。例如,已知如下枚举类型:

enum status{bad,ok};

    相关联的值是0和1。这两个值可以(但不必须)存放在char类型中。当这些值实际上被作为char类型存储时候,char代表了枚举的底层类型。然后,status的整值提升姜它的底层类型转换为int。

    尽管算术转换的这些规则可能给你的困惑多于启发,但是,一般的思想是,尽可能地保留多类型表达式中涉及到的值的精度。者正是通过“把不同类型提升到当前出现的最宽的类型”来实现的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值