类型转换

来源:互联网 发布:可牛闪图软件下载 编辑:程序博客网 时间:2024/06/08 13:51

int i = 3;

double d = 3.14;

i = i + d;

整型与浮点型相加,编译器为保证精度,首先会将整型转化成浮点型,然后求和,所以i+d的结果为浮点型6.14,但将一个浮点型值赋给一个整型变量,精度会发生损失,所以最终结果为6.14

算术转换规则定义了一个类型转换层次,该层次规定了操作数应按什么次序转换为表达式中最宽的类型。在包含多种类型的表达式中,转换规则要确保计算值的精度。例如,如果一个操作数的类型是 long double,则无论另一个操作数是什么类型,都将被转换为 long double。

最简单的转换为整型提升:对于所有比 int 小的整型,包括 char、signed char、unsigned char、short 和 unsigned short,如果该类型的所有可能的值都能包容在 int 内,它们就会被提升为 int 型,否则,它们将被提升为 unsigned int。如果将 bool 值提升为 int ,则 false 转换为 0,而 true 则转换为 1。

若表达式中使用了无符号( unsigned )数值,所定义的转换规则需保护操作数的精度。unsigned 操作数的转换依赖于机器中整型的相对大小,因此,这类转换本质上依赖于机器。

包含 short 和 int 类型的表达式, short 类型的值转换为 int 。如果 int 型足够表示所有 unsigned short 型的值,则将 unsigned short 转换为 int,否则,将两个操作数均转换为 unsigned int 。例如,如果 short 用半字表示而 int 用一个字表示,则所有 unsigned 值都能包容在 int 内,在这种机器上, unsigned short 转换为 int。


long 和 unsigned int 的转换也是一样的。只要机器上的 long 型足够表示 unsigned int 型的所有值,就将 unsigned int 转换为 long 型,否则,将两个操作数均转换为 unsigned long 。


在 32 位的机器上,long 和 int 型通常用一个字长表示,因此当表达式包含 unsigned int 和 long 两种类型,其操作数都应转换为 unsigned long 型。


对于包含 signed 和 unsigned int 型的表达式,其转换可能出乎我们的意料。表达式中的 signed 型数值会被转换为 unsigned 型。例如,比较 int 型和 unsigned int 型的简单变量,系统首先将 int 型数值转换为 unsigned int 型,如果 int 型的值恰好为负数,怎么办????

在使用数组时,大多数情况下数组都会自动转换为指向第一个元素的指针:

  int ia[10]; // array of 10 ints
  int* ip = ia; // convert ia to pointer to first element

不将数组转换为指针的例外情况有:数组用作取地址(&)操作符的操作数或 sizeof 操作符的操作数时,或用数组对数组的引用进行初始化时,不会将数组转换为指针。

算术值和指针值都可以转换为 bool 类型。如果指针或算术值为 0,则其 bool 值为 false ,而其他值则为 true:

  if (cp) /* ... */ // true if cp is not zero
  while (*cp) /* ... */ // dereference cp and convert resulting char to bool

这里,if 语句将 cp 的非零值转换为 true。 while 语句则对 cp 进行解引用,操作结果产生一个 char 型的值。空字符( null )具有 0 值,被转换为 false,而其他字符值则转换为 true。


可将算术对象转换为 bool 类型,bool 对象也可转换为 int 型。将算术类型转换为 bool 型时,零转换为 false ,而其他值则转换为 true 。将 bool 对象转换为算术类型时,true 变成 1,而 false 则为 0:

  bool b = true;
  int ival = b; // ival == 1
  double pi = 3.14;
  bool b2 = pi; // b2 is true
  pi = false; // pi == 0


C++ 自动将枚举类型的对象或枚举成员( enumerator )转换为整型,其转换结果可用于任何要求使用整数值的地方。例如,用于算术表达式:

  // point2d is 2, point2w is 3, point3d is 3, point3w is 4
  enum Points { point2d = 2, point2w,
  point3d = 3, point3w };
  const size_t array_size = 1024;
  // ok: pt2w promoted to int
  int chunk_size = array_size * pt2w;
  int array_3d = array_size * point3d;

将 enum 对象或枚举成员提升为什么类型由机器定义,并且依赖于枚举成员的最大值。无论其最大值是什么, enum 对象或枚举成员至少提升为 int 型。如果 int 型无法表示枚举成员的最大值,则提升到能表示所有枚举成员值的、大于 int 型的最小类型( unsigned int、long 或 unsigned long)。

类类型可以定义由编译器自动执行的类型转换。迄今为止,我们使用过的标准库类型中,有一个重要的类型转换。从 istream 中读取数据,并将此表达式作为 while 循环条件:

  string s;
  while (cin >> s)

这里隐式使用了 IO 标准库定义的类型转换。在与此类似的条件中,求解表达式 cin >> s,即读 cin。无论读入是否成功,该表达式的结果都是 cin。

while 循环条件应为 bool 类型的值,但此时给出的却是 istream 类类型的值,于是 istream 类型的值应转换为 bool 类型。将 istream 类型转换为 bool 类型意味着要检验流的状态。如果最后一次读 cin 的尝试是成功的,则流的状态将导致上述类型转换为 bool 类型后获得 true 值——while 循环条件成立。如果最后一次尝试失败,比如说已经读到文件尾了,此时将 istream 类型转换为 bool 类型后得 false,while 循环条件不成立。