C++Primer快速浏览笔记-类型转换

时间:2023-03-09 04:06:21
C++Primer快速浏览笔记-类型转换
  1. bool b = 42; // _b is true_
  2. int i = b; // _i has value 1_
  3. i = 3.14; // _i has value 3_
  4. double pi = i; // _pi has value 3.0_
  5. unsigned char c = -1; // _assuming 8-bit chars_, _c has value 255_
  6. signed char c2 = 256; // _assuming 8-bit chars_, _the value of c2 is__undefined_

类型所能表示的值的范围决定了转换的过程:

  • 当我们把一个非布尔类型的算术值赋给布尔类型时,初始值为0则结果为false,
    否则结果为true.
  • 当我们把一个布尔值赋给非布尔类型时,初始值为false则结果为O,初始值为
    true则结果为1.
  • 当我们把一个浮点数赋给整数类型时,进行了近似处理。结果值将仅保留浮点数中
    小数点之前的部分。
  • 当我们把一个整数值赋给浮点类型时,小数部分记为0。如果该整数所占的空间超
    过了浮点类型的容量,精度可能有损失。
  • 当我们赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表
    示数值总数取模后的余数。例如,8比特大小的unsigned char可以表示0至255区间内的值,如果我们赋了一个区间以外的值,则实际的结果是该值对256取模后所得的余数(负数加上无符号数的模,这里模=x2)。因此,把-1赋给8比特大小的unsigned char所得的结果是255.

    在计算机系统中,数值一律用补码来表示和存储,正整数的补码是其二进制表示,与原码相同;负整数的补码,将其对应正数二进制表示所有位取反(包括符号位,0变1,1变0)后加1。-1的原码10000001 转换成补码:11111111,因此将其看做无符号的正整数,其值为255.

  • 当我们赋给带符号类型一个超出它表示范围的值时,结果是未定义的(undefined)。
    此时工程程序可能继续工作、可能崩溃,也可能生成垃圾数据。
    资料补充
    算数运算中自动类型转换
    基本原则:值域较窄的类型向值域较宽的类型转换
    C++Primer快速浏览笔记-类型转换
    同时要注意以下3点:
  1. 表达式中的有符号和无符号字符(针对字符)以及短整型一律被转换为整型, 如果int类型能表示原来类型的值,则转换成int类型;否则转换成unsigned类型。
  2. 当一个运算量为long类型, 另一个为unsigned类型时,如果long能表示unsigned的全部值, 则将unsigned转换成long; 否则将两个运算量都转换为unsigned long。
  3. 当两个运算量中值域较宽的类型是float类型时, 不再将float和另一运算量转换成double类型

这里需要注意有符号数与无符号数之间运算问题
当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此,从这个意义上讲,无符号数的运算优先级要高于有符号数。
下面的实验来自网友,本人在VS2013平台进行了验证:

首先进行一个实验,分别定义一个signed int型数据和unsigned int型数据,然后进行大小比较:
unsigned int a=20;
signed int b=-130;
a>b?还是b>a?实验证明b>a,也就是说-130>20,为什么会出现这样的结果呢?
这是因为在C语言操作中,如果遇到无符号数与有符号数之间的操作,编译器会自动转化为无符号数来进行处理,因此a=20,b=4294967166,这样比较下去当然b>a了。
再举一个例子:
unsigned int a=20;
signed int b=-130;
std::cout<<a+b<<std::endl;
结果输出为4294967186,同样的道理,在运算之前,a=20,b被转化为4294967166,所以a+b=4294967186
减法和乘法的运算结果类似。
如果作为signed int型数据的b=-130,b与立即数之间操作时不影响b的类型,运算结果仍然为signed int型:
signed int b=-130;
std::cout<<b+30<<std::endl;
输出为-100。
而对于浮点数来说,浮点数(float,double)实际上都是有符号数,unsigned 和signed前缀不能加在float和double之上,当然就不存在有符号数根无符号数之间转化的问题了。

这样一个题,据说是微软面试题:
unsigned int i=3;
cout<<i -1;
问结果是多少。
第一反应:-3。不过结果似乎不是这样的,写了个程序,运行了一下,发现是:4294967293。
在32位机上,int型和unsigned int型都是32位的(4个字节),在表达式i
-1中,i是unsigned int型,-1是int型(常量整数的类型同enum),按第5条可以知道-1必须转换为unsigned int型,即0xffffffff,十进制的4294967295,然后再与i相乘,即4294967295*3,如果不考虑溢出的话,结果是12884901885,十六进制0x2FFFFFFFD,由于unsigned int只能表示32位,忽略高四位,因此结果是0xfffffffd,即4294967293。

再比如《C++Primer中文版·第五版》中有个说明:

当从无符号数中减去一个值时,不管这个值是不是无符号数,我们必须确保结果不能是一个负值。书中给出的例子是:

  1. unsigned u1 = 42, u2 = 10;
  2. std::cout << u1 - u2 << std::endl; //正确,输出32
  3. std::cout << u2 - u1 << std::endl; //正确;不过,结果是取模后的值

结果是:

232−32=4294967264