C ++运算符中的隐式类型转换规则

时间:2011-04-06 07:44:20

标签: c++ casting implicit

我想知道什么时候应该投出更好。在添加,乘法等时,C ++中的隐式类型转换规则是什么。例如,

int + float = ?
int * float = ?
float * int = ?
int / float = ?
float / int = ?
int / int = ?
int ^ float = ?

等等......

表达式是否总是被评估为更精确的类型? Java的规则有所不同吗? 如果我不准确地说出这个问题,请纠正我。

9 个答案:

答案 0 :(得分:194)

在C ++中,运算符(对于POD类型)总是对相同类型的对象起作用 因此,如果它们不相同,那么它将被提升以匹配另一个 操作结果的类型与操作数相同(转换后)。

If either is      long          double the other is promoted to      long          double
If either is                    double the other is promoted to                    double
If either is                    float  the other is promoted to                    float
If either is long long unsigned int    the other is promoted to long long unsigned int
If either is long long          int    the other is promoted to long long          int
If either is long      unsigned int    the other is promoted to long      unsigned int
If either is long               int    the other is promoted to long               int
If either is           unsigned int    the other is promoted to           unsigned int
If either is                    int    the other is promoted to                    int
Both operands are promoted to int

请注意。最小操作大小为int。因此,short / char会在操作完成之前升级为int

在所有表达式中,int在执行操作之前被提升为float。操作的结果是float

int + float =>  float + float = float
int * float =>  float * float = float
float * int =>  float * float = float
int / float =>  float / float = float
float / int =>  float / float = float
int / int                     = int
int ^ float =>  <compiler error>

答案 1 :(得分:30)

涉及float的算术运算会产生float

int + float = float
int * float = float
float * int = float
int / float = float
float / int = float
int / int = int

了解更多详情。看看C ++标准中第5/9节的内容是什么

  

许多期望的二元运算符   算术或枚举的操作数   类型导致转换和产量   结果类型以类似的方式。该   目的是产生一个共同的类型,   也是结果的类型

     

这种模式通常被称为   算术转换,是   定义如下:

     

- 如果任一操作数的类型为long   双,另一个应转换   长一倍。

     

- 否则,如果是   操作数是双倍的,另一个是   转换为双倍。

     

- 否则,如果   操作数是浮点数,另一个是浮点数   应转换为浮动。

     

- 否则,积分促销   (4.5)应在两者上进行   operands.54)

     

- 然后,如果是任一操作数   另一个应该是无符号的   转换为无符号长。

     

- 否则,如果一个操作数很长   那么int和另一个unsigned int   如果一个long int可以代表所有的   unsigned int的值,   unsigned int应转换为a   long int;否则两个操作数   应转换为无符号长   INT。

     

- 否则,如果任一操作数是   长,另一个应转换为   长。

     

- 否则,如果是任一操作数   是未签名的,另一个是   转换为无符号。

     

[注意:否则,唯一剩下的情况是   两个操作数都是int]

答案 2 :(得分:16)

由于其他答案没有谈到C ++ 11中的规则,所以这里是一个。从C ++ 11标准(草案n3337)§5/ 9:

  

此模式称为通常的算术转换,其定义如下:

     

- 如果任一操作数是作用域枚举类型,则不执行任何转换;如果另一个操作数的类型不同,则表达式格式不正确。

     

- 如果任一操作数的类型为long double,则另一个操作数应转换为long double。

     

- 否则,如果任一操作数为double,则另一个操作数应转换为double。

     

- 否则,如果任一操作数是浮点数,则另一个操作数应转换为浮点数。

     

- 否则,应对两个操作数执行整体促销。然后,以下规则应适用于提升的操作数:

     
    

- 如果两个操作数具有相同的类型,则不需要进一步转换。

         

- 否则,如果两个操作数都有有符号整数类型或两者都有无符号整数类型,则     具有较小整数转换等级类型的操作数应转换为类型     操作数更高的等级。

         

- 否则,如果具有无符号整数类型的操作数的等级大于或等于     另一个操作数的类型的等级,带有符号整数类型的操作数应转换为     具有无符号整数类型的操作数的类型。

         

- 否则,如果带有符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数类型的所有值,则带有无符号整数类型的操作数应为     转换为带有符号整数类型的操作数的类型。

         

- 否则,两个操作数都应转换为对应的无符号整数类型     带有符号整数类型的操作数的类型。

  

有关经常更新的列表,请参阅here

答案 3 :(得分:5)

这个答案在很大程度上取决于@RafałDowgird的评论:

  

“操作的最小大小为int。” - 这很奇怪   (那些有效支持char / short的架构呢?   操作?)这真的是在C ++规范中吗?

请记住,C ++标准具有非常重要的“as-if”规则。请参见第1.8节:程序执行:

  

3)这项规定有时被称为“as-if”规则,因为a   实施可以自由地忽视标准的任何要求   只要结果好像已经遵守要求,到目前为止   可以从程序的可观察行为中确定。

编译器无法将int设置为8位,即使它是最快的,因为标准要求最小16位int

因此,对于具有超快速8位操作的理论计算机,对算术的int的隐式提升可能很重要。但是,对于许多操作,您无法判断编译器是否实际以int的精度执行了操作,然后转换为char以存储在您的变量中,或者操作是否在char中完成一直以来。

例如,考虑unsigned char = unsigned char + unsigned char + unsigned char,其中加法会溢出(让我们假设每个值为200)。如果你升级到int,你将获得600,然后将隐式地下放到unsigned char,这将包装模256,从而给出88的最终结果。如果你没有这样的促销,你必须在前两个添加之间进行换行,这会将问题从200 + 200 + 200减少到144 + 200,即344,减少到88.换句话说,程序不知道差异,因此如果操作数的排名低于int,编译器可以自由地忽略在int中执行中间操作的任务。

一般来说,加法,减法和乘法都是如此。对于除法或模数,一般情况并非如此。

答案 4 :(得分:3)

如果排除无符号类型,则会有序 层次结构:signed char,short,int,long,long long,float, 双倍,长双。首先,在int之前的任何事情 以上将转换为int。然后,在二进制操作中, 排名较低的类型将转换为更高的,和 结果将是更高的类型。 (你会注意到,来自 层次结构,任何时候浮点和整数类型 涉及时,积分类型将转换为浮动 点类型。)

无符号使事情变得复杂:它扰乱了排名,并且 排名的一部分成为实现定义。因为 这个,最好不要混合使用signed和unsigned 表达。 (大多数C ++专家似乎都避免使用unsigned 涉及按位操作。那至少是什么 Stroustrup建议。)

答案 5 :(得分:2)

我的solution problem获得了WA(错误的答案),然后我将int中的一个更改为long long int,并且它给了AC(accept)。以前,我正在尝试long long int += int * int,并在我将其纠正为long long int += long long int * int之后。谷歌搜索我想出来,

1。 Arithmetic Conversions

类型转换的条件:

条件符合---&gt;转化

  • 任一操作数的类型为 long double 。 ---&GT;其他操作数转换为 long double 类型。

  • 未满足前置条件且任一操作数的类型为 double 。 ---&GT;其他操作数转换为 double 类型。

  • 未满足前面的条件且任一操作数的类型为 float 。 ---&GT;其他操作数转换为 float 类型。

  • 未满足前置条件(没有任何操作数属于浮点类型)。 ---&GT;对操作数执行整体促销,如下所示:

    • 如果任一操作数的类型为 unsigned long ,则另一个操作数将转换为 unsigned long 类型。
    • 如果未满足先前条件,并且任一操作数的类型为而另一个操作数类型为 unsigned int ,则两个操作数都将转换为 unsigned long类型即可。
    • 如果不满足前两个条件,并且任一操作数的类型为 long ,则其他操作数将转换为 long 类型。
    • 如果不满足前面三个条件,并且如果任一操作数的类型为 unsigned int ,则另一个操作数将转换为 unsigned int 类型。
    • 如果不满足上述条件,则两个操作数都将转换为 int 类型。

2。 Integer conversion rules

  • 整数促销:

对它们执行操作时,会提升小于int的整数类型。如果原始类型的所有值都可以表示为int,则较小类型的值将转换为int;否则,它将转换为unsigned int。整数促销作为通常算术转换的一部分应用于某些参数表达式;一元+, - 和〜运算符的操作数;移位运营商的操作和操作。

  • 整数转换排名:

    • 没有两个有符号整数类型具有相同的等级,即使它们具有相同的表示。
    • 有符号整数类型的等级应大于精度较低的任何有符号整数类型的等级。
    • long long int的排名应大于long int的排名,int的排名应大于short int的排名,signed char的排名应大于char的排名},应大于signed char的等级。
    • 任何无符号整数类型的等级应等于相应的有符号整数类型的等级(如果有)。
    • 任何标准整数类型的等级应大于具有相同宽度的任何扩展整数类型的等级。
    • unsigned char的等级应等于{{1}}和{{1}}的等级。
    • 任何扩展有符号整数类型相对于具有相同精度的另一个扩展有符号整数类型的等级是实现定义的,但仍然受制于确定整数转换等级的其他规则。
    • 对于所有整数类型T1,T2和T3,如果T1的等级大于T2且T2的等级大于T3,则T1的等级大于T3。
  • 通常的算术转换:

    • 如果两个操作数具有相同的类型,则无需进一步转换。
    • 如果两个操作数具有相同的整数类型(有符号或无符号),则具有较小整数转换等级类型的操作数将转换为具有较高等级的操作数的类型。
    • 如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的等级,则带有符号整数类型的操作数将转换为具有无符号整数类型的操作数的类型。
    • 如果带有符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数类型的所有值,则具有无符号整数类型的操作数将转换为带有符号整数类型的操作数的类型。 / LI>
    • 否则,两个操作数都将转换为无符号整数类型,对应于带有符号整数类型的操作数类型。具体操作可以添加或修改通常的算术运算的语义。

答案 6 :(得分:1)

当两个部分属于同一类型时,表达式的类型将转换为两者的最大。这里的问题是要了解哪一个比另一个大(它与字节大小没有任何关系)。

在涉及实数和整数的表达式中,整数将被提升为实数。例如,在int + float中,表达式的类型为float。

另一个区别与该类型的能力有关。例如,涉及int和long int的表达式将导致类型为long int。

答案 7 :(得分:1)

整个第4章讨论了转换,但我认为你应该对这些转换感兴趣:

4.5整体促销 [conv.prom]
char,signed char,unsigned char,short int或unsigned short的rvalue 如果int可以表示源类型的所有值,则int可以转换为int类型的rvalue;其他 -
明智的是,源rvalue可以转换为unsigned int类型的右值 可以将类型为wchar_t(3.9.1)或枚举类型(7.2)的右值转换为第一个的右值 可以表示其基础类型的所有值的以下类型:int,unsigned int,
长期或无签名长 如果int可以表示全部,则可以将积分位域(9.6)的rvalue转换为int类型的rvalue 位域的值;否则,如果unsigned int可以转换为它,则可以转换为unsigned int 重新发现位域的所有值。如果位字段较大,则不适用整数提升。如果是 bit-field具有枚举类型,它被视为该类型的任何其他值以用于促销目的 bool类型的rvalue可以转换为int类型的rvalue,false变为零且为真 成为一个。
这些转化称为整体促销。

4.6浮点促销 [conv.fpprom]
float类型的右值可以转换为double类型的右值。价值没有变化 此转换称为浮点提升。

因此,涉及float的所有转换 - 结果都是float。

只涉及两个int - 结果是int: int / int = int

答案 8 :(得分:-1)

买者!

转换从左到右进行。

试试这个:

int i = 3, j = 2;
double k = 33;
cout << k * j / i << endl; // prints 22
cout << j / i * k << endl; // prints 0