分享

C/C++中自动类型转换的规则

 戴维图书馆 2014-05-30

C/C++中自动类型转换的规则

shawpinlee posted @ 2007年9月16日 23:04 in C/C++ , 4802 阅读

 

C++定义了一组内置类型对象之间的标准转换,在必要时它们被编译器隐式地应用到对象上。

隐式类型转换发生在下列这些典型情况下:

1. 在混合类型的算术表达式中

在这种情况下最宽的数据类型成为目标转换类型,这也被称为算术转换,例如:

 

int ival = 3;
double dval = 3.14159;
//ival 被提升为double类型: 3.0
ival+dval;

2.用一种类型的表达式赋值给另一种类型的对象

在这种情况下目标转换类型是被赋值对象的类型。例如在下面第一个赋值中文字常量0的类型是int。它被转换成int*型的指针表示空地址。在第二个赋值中double类型的值被截取成int型的值。

// 0被转换成int*类型的空指针值
int *pi = 0;
//dval被截取为int值 3
ival = daval;

3.  把一个表达式传递给一个函数,调用表达式的类型与形式参数的类型不相同

在这种情况下目标转换类型是形式参数的类型。例如:

 

extern double sqrt( double);
//2 被提升为 double类型2.0
cout<< "The square root of 2 is "<< sqrt(2) <<endl;

4.从一个函数返回一个表达式的类型与返回类型不同

在这种情况下返回的表达式类型自动转换成函数的返回类型。例如:

double difference(int ival1, int ival2)
{
    //返回值被提升为 double类型
   return ival1- ival2;
}

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

(1) 为防止精度损失,如果必要的话,类型总是被提升为较宽的类型

(2) 所有含有小于整型的有序类型的算术表达式在计算之前其类型都会被转换成整型。

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

如果一个操作数的类型是long double,那么另一个操作数无论是什么类型都要被转换成long double。例如在下面的表达式中,字符常量小写字符a将被提升为long double,它的ASCII码值为97,然后再被加到long double型的文字常量上:

3.14159L + 'a';

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

 

int ival;
float fval;
double dval;

//在计算加法前fval 和 ival都被转换成double
dval + faval + ival;

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

char cval;
int ival;
float fval;
//在计算加法前ival和cval都被转换成double
cval+fval+ival;
 

 

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

在进行整值提升时类型char、signed char、unsigned char和short int都被提升为类型 int。如果机器上的类型空间足够表示所有unsigned short 型的值,这通常发生在short用半个字而int用一个字表示的情况下,则unsigned short int也被转换成int,否则它会被提升为unsigned int。wchar_t和枚举类型被提升为能够表示其底层类型(underlying type)和所有值的最小整数类型。例如已知如下枚举类型:

enum status {bad, ok};

相关联的值是0和1。这两个值可以但不是必须存放在char类型的表示中。当这些值实际上被作为char类型来存储时,char代表了枚举的底层类型,然后status的整体提升将它的题曾类型转换为int。在下列表达式中:

 

 

char cval;
bool found;
enum mumble{m1,m2,m3} mval;
unsigned long ulong;
cval + ulong ;
ulong+found;
mval+ulong;

 

在确定两个操作数被提升的公共类型之前,cval found和mval都被提升为int类型。

一旦整体提升执行嗯完毕,类型比较就又一次开始。如果一个操作数是unsigned long型,则第二个转换也被转换成unsigned long型。在上面的例子中所有被加到ulong上的3个对象都被提升为unsigned long型。如果两个操作数的类型都不是unsigned long而其中一个操作数是long型,则另一个也被转换成long型。例如:

 

char cval;
long lval;
// 在计算加法前cval和1024都被提升为long型
cval+1024+lval;

 

long类型的一般转换有一个例外。如果一个操作数是long型而另一个是unsigned int型,那么只有在机器上的long型的长度足以存放unsigned int的所有值时(一般来说,在32位操作系统中long型和 int 型都用一个字长表示,所以不满足这里的假设条件),unsigned int才会被转为long型,否则两个操作数都被提升为 unsigned long 型。若两个操作数都不是long型而其中一个是unsigned int型,则另一个也被转换成unsigned int型,否则两个操作数一定都是int型。

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

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多