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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5563000/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:25:24  来源:igfitidea点击:

Implicit type conversion rules in C++ operators

c++castingimplicit

提问by Matt Montag

I want to be better about knowing when I should cast. What are the implicit type conversion rules in C++ when adding, multiplying, etc. For example,

我想更好地知道什么时候应该投。C++中加、乘等的隐式类型转换规则有哪些,比如

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

et cetera...

等等...

Will the expression always be evaluated as the more precise type? Do the rules differ for Java? Please correct me if I have worded this question inaccurately.

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

回答by Martin York

In C++ operators (for POD types) always act on objects of the same type.
Thus if they are not the same one will be promoted to match the other.
The type of the result of the operation is the same as operands (after conversion).

在 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

Note. The minimum size of operations is int. So short/charare promoted to intbefore the operation is done.

笔记。操作的最小规模是int。所以short/在操作完成之前char被提升到int

In all your expressions the intis promoted to a floatbefore the operation is performed. The result of the operation is a float.

在您的所有表达式中,在执行操作之前将int提升为 a 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>

回答by Nawaz

Arithmetic operations involving floatresults in float.

涉及float结果的算术运算float

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

For more detail answer. Look at what the section §5/9 from the C++ Standard says

更详细的答案。看看 C++ 标准第 5/9 节的内容

Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result.

This pattern is called the usual arithmetic conversions, which are defined as follows:

— If either operand is of type long double, the other shall be converted to long double.

— Otherwise, if either operand is double, the other shall be converted to double.

— Otherwise, if either operand is float, the other shall be converted to float.

— Otherwise, the integral promotions (4.5) shall be performed on both operands.54)

— Then, if either operand is unsigned long the other shall be converted to unsigned long.

— Otherwise, if one operand is a long int and the other unsigned int, then if a long int can represent all the values of an unsigned int, the unsigned int shall be converted to a long int; otherwise both operands shall be converted to unsigned long int.

— Otherwise, if either operand is long, the other shall be converted to long.

— Otherwise, if either operand is unsigned, the other shall be converted to unsigned.

[Note: otherwise, the only remaining case is that both operands are int ]

许多期望算术或枚举类型的操作数的二元运算符会以类似的方式导致转换并产生结果类型。目的是产生一个通用类型, 它也是 result 的类型

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

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

— 否则,如果任一操作数为双精度,则另一个应转换为双精度。

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

— 否则,应在两个操作数上执行积分提升 (4.5)。54)

— 然后,如果任一操作数是 unsigned long,则另一个应转换为 unsigned long。

——否则,如果一个操作数是一个long int而另一个是unsigned int,那么如果一个long int可以表示一个unsigned int的所有值,那么这个unsigned int就应该被转换成一个long int;否则两个操作数都应转换为 unsigned long int。

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

— 否则,如果任一操作数是无符号的,则另一个应转换为无符号。

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

回答by legends2k

Since the other answers don't talk about the rules in C++11 here's one. From C++11 standard (draft n3337) §5/9 (emphasized the difference):

由于其他答案没有讨论 C++11 中的规则,这里是一个。来自 C++11 标准(n3337 草案)§5/9(强调差异):

This pattern is called the usual arithmetic conversions, which are defined as follows:

— If either operand is of scoped enumeration type, no conversions are performed; if the other operand does not have the same type, the expression is ill-formed.

— If either operand is of type long double, the other shall be converted to long double.

— Otherwise, if either operand is double, the other shall be converted to double.

— Otherwise, if either operand is float, the other shall be converted to float.

— Otherwise, the integral promotions shall be performed on both operands. Then the following rules shall be applied to the promoted operands:

— If both operands have the same type, no further conversion is needed.

— Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank shall be converted to the type of the operand with greater rank.

— Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type.

— Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type.

— Otherwise, both operands shall be converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

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

— 如果任一操作数是作用域枚举类型,则不执行任何转换;如果另一个操作数不具有相同的类型,则表达式格式错误。

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

— 否则,如果任一操作数为双精度,则另一个应转换为双精度。

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

— 否则,两个操作数都要进行积分提升。然后将以下规则应用于提升的操作数:

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

— 否则,如果两个操作数都是有符号整数类型或者都是无符号整数类型,则将整数转换等级较小的操作数转换为等级较大的操作数的类型。

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

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

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

See herefor a list that's frequently updated.

请参阅此处获取经常更新的列表。

回答by David Stone

This answer is directed in large part at a comment made by @Rafa?Dowgird:

这个答案很大程度上是针对@Rafa?Dowgird 发表的评论:

"The minimum size of operations is int." - This would be very strange (what about architectures that efficiently support char/short operations?) Is this really in the C++ spec?

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

Keep in mind that the C++ standard has the all-important "as-if" rule. See section 1.8: Program Execution:

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

3) This provision is sometimes called the "as-if" rule, because an implementation is free to disregard any requirement of the Standard as long as the result is as if the requirement had been obeyed, as far as can be determined from the observable behavior of the program.

3) 这条规定有时被称为“as-if”规则,因为只要结果好像要求已被遵守,就可以从可观察到的范围内确定,实施可以自由地无视标准的任何要求程序的行为。

The compiler cannot set an intto be 8 bits in size, even if it were the fastest, since the standard mandates a 16-bit minimum int.

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

Therefore, in the case of a theoretical computer with super-fast 8-bit operations, the implicit promotion to intfor arithmetic could matter. However, for many operations, you cannot tell if the compiler actually did the operations in the precision of an intand then converted to a charto store in your variable, or if the operations were done in char all along.

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

For example, consider unsigned char = unsigned char + unsigned char + unsigned char, where addition would overflow (let's assume a value of 200 for each). If you promoted to int, you would get 600, which would then be implicitly down cast into an unsigned char, which would wrap modulo 256, thus giving a final result of 88. If you did no such promotions,you'd have to wrap between the first two additions, which would reduce the problem from 200 + 200 + 200to 144 + 200, which is 344, which reduces to 88. In other words, the program does not know the difference, so the compiler is free to ignore the mandate to perform intermediate operations in intif the operands have a lower ranking than int.

例如,考虑unsigned char = unsigned char + unsigned char + unsigned char,其中加法会溢出(假设每个值为 200)。如果你升级到int,你会得到 600,然后它会被隐式转换成一个unsigned char,它会包装模 256,从而得到 88 的最终结果。如果你没有这样的提升,你必须在第一个之间换行两个加法,将问题从200 + 200 + 200to144 + 200减少到 344,减少到 88。 换句话说,程序不知道差异,因此int如果操作数有,编译器可以随意忽略执行中间操作的任务排名低于int.

This is true in general of addition, subtraction, and multiplication. It is not true in general for division or modulus.

这在加法、减法和乘法中普遍适用。对于除法或模数而言,通常情况并非如此。

回答by James Kanze

If you exclude the unsigned types, there is an ordered hierarchy: signed char, short, int, long, long long, float, double, long double. First, anything coming before int in the above will be converted to int. Then, in a binary operation, the lower ranked type will be converted to the higher, and the results will be the type of the higher. (You'll note that, from the hierarchy, anytime a floating point and an integral type are involved, the integral type will be converted to the floating point type.)

如果排除无符号类型,则有一个有序的层次结构:signed char、short、int、long、long long、float、double、long double。首先,上面的 int 之前的任何内容都将转换为 int。然后,在二元运算中,将排名较低的类型转换为较高的类型,结果将是较高的类型。(您会注意到,从层次结构中,只要涉及浮点类型和整数类型,整数类型就会转换为浮点类型。)

Unsigned complicates things a bit: it perturbs the ranking, and parts of the ranking become implementation defined. Because of this, it's best to not mix signed and unsigned in the same expression. (Most C++ experts seem to avoid unsigned unless bitwise operations are involved. That is, at least, what Stroustrup recommends.)

无符号使事情变得有点复杂:它扰乱了排名,并且部分排名变得由实现定义。因此,最好不要在同一个表达式中混合使用有符号和无符号。(大多数 C++ 专家似乎避免无符号,除非涉及按位运算。至少,这是 Stroustrup 推荐的。)

回答by garakchy

My solutionto the problemgot WA(wrong answer), then i changed one of intto long long intand it gave AC(accept). Previously, I was trying to do long long int += int * int, and after I rectify it to long long int += long long int * int. Googling I came up with,

我对问题的解决方案得到了 WA(wrong answer),然后我将其中一个改为to并给出了AC(accept)。以前,我试图做,然后我将其纠正为. 我想出的谷歌搜索,intlong long intlong long int += int * intlong long int += long long int * int

1. Arithmetic Conversions

1.算术转换

Conditions for Type Conversion:

类型转换的条件:

Conditions Met ---> Conversion

满足条件 ---> 转换

  • Either operand is of type long double. ---> Other operand is converted to type long double.

  • Preceding condition not met and either operand is of type double. ---> Other operand is converted to type double.

  • Preceding conditions not met and either operand is of type float. ---> Other operand is converted to type float.

  • Preceding conditions not met (none of the operands are of floating types). ---> Integral promotions are performed on the operands as follows:

    • If either operand is of type unsigned long, the other operand is converted to type unsigned long.
    • If preceding condition not met, and if either operand is of type longand the other of type unsigned int, both operands are converted to type unsigned long.
    • If the preceding two conditions are not met, and if either operand is of type long, t he other operand is converted to type long.
    • If the preceding three conditions are not met, and if either operand is of type unsigned int, the other operand is converted to type unsigned int.
    • If none of the preceding conditions are met, both operands are converted to type int.
  • 任一操作数的类型为long double。---> 其他操作数转换为long double类型。

  • 不满足前面的条件,并且任一操作数的类型为double。---> 其他操作数转换为double类型。

  • 不满足前面的条件,并且任一操作数的类型为float。---> 其他操作数转换为float类型。

  • 不满足前面的条件(所有操作数都不是浮点类型)。---> 对操作数执行积分提升如下:

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

2 . Integer conversion rules

2 . 整数转换规则

  • Integer Promotions:
  • 整数促销:

Integer types smaller than int are promoted when an operation is performed on them. If all values of the original type can be represented as an int, the value of the smaller type is converted to an int; otherwise, it is converted to an unsigned int. Integer promotions are applied as part of the usual arithmetic conversions to certain argument expressions; operands of the unary +, -, and ~ operators; and operands of the shift operators.

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

  • Integer Conversion Rank:

    • No two signed integer types shall have the same rank, even if they have the same representation.
    • The rank of a signed integer type shall be greater than the rank of any signed integer type with less precision.
    • The rank of long long intshall be greater than the rank of long int, which shall be greater than the rank of int, which shall be greater than the rank of short int, which shall be greater than the rank of signed char.
    • The rank of any unsigned integer type shall equal the rank of the corresponding signed integer type, if any.
    • The rank of any standard integer type shall be greater than the rank of any extended integer type with the same width.
    • The rank of charshall equal the rank of signed charand unsigned char.
    • The rank of any extended signed integer type relative to another extended signed integer type with the same precision is implementation-defined but still subject to the other rules for determining the integer conversion rank.
    • For all integer types T1, T2, and T3, if T1 has greater rank than T2 and T2 has greater rank than T3, then T1 has greater rank than T3.
  • Usual Arithmetic Conversions:

    • If both operands have the same type, no further conversion is needed.
    • If both operands are of the same integer type (signed or unsigned), the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.
    • If the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type is converted to the type of the operand with unsigned integer type.
    • If the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type is converted to the type of the operand with signed integer type.
    • Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type. Specific operations can add to or modify the semantics of the usual arithmetic operations.
  • 整数转换等级:

    • 任何两个有符号整数类型都不应具有相同的等级,即使它们具有相同的表示形式。
    • 有符号整数类型的等级应大于精度较低的任何有符号整数类型的等级。
    • 等级long long int应大于等级long int,等级大于等级int,等级大于等级short int,等级大于等级signed char
    • 任何无符号整数类型的等级应等于相应的有符号整数类型(如果有)的等级。
    • 任何标准整数类型的秩都应大于具有相同宽度的任何扩展整数类型的秩。
    • 军衔char应等于的秩signed charunsigned char
    • 任何扩展有符号整数类型相对于具有相同精度的另一个扩展有符号整数类型的等级是实现定义的,但仍受用于确定整数转换等级的其他规则的约束。
    • 对于所有整数类型 T1、T2 和 T3,如果 T1 的秩大于 T2 且 T2 的秩大于 T3,则 T1 的秩大于 T3。
  • 通常的算术转换:

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

回答by Baltasarq

The type of the expression, when not both parts are of the same type, will be converted to the biggestof both. The problem here is to understand which one is bigger than the other (it does not have anything to do with size in bytes).

表达式的类型,当两个部分不是相同类型时,将转换为两者中最大的。这里的问题是要了解哪个比另一个大(它与字节大小无关)。

In expressions in which a real number and an integer number are involved, the integer will be promoted to real number. For example, in int + float, the type of the expression is float.

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

The other difference are related to the capability of the type. For example, an expression involving an int and a long int will result of type long int.

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

回答by B?ови?

Whole chapter 4 talks about conversions, but I think you should be mostly interested in these :

整个第 4 章都在讨论转换,但我认为您应该对这些最感兴趣:

4.5 Integral promotions[conv.prom]
An rvalue of type char, signed char, unsigned char, short int, or unsigned short int can be converted to an rvalue of type int if int can represent all the values of the source type; other-
wise, the source rvalue can be converted to an rvalue of type unsigned int.
An rvalue of type wchar_t (3.9.1) or an enumeration type (7.2) can be converted to an rvalue of the first
of the following types that can represent all the values of its underlying type: int, unsigned int,
long, or unsigned long.
An rvalue for an integral bit-field (9.6) can be converted to an rvalue of type int if int can represent all
the values of the bit-field; otherwise, it can be converted to unsigned int if unsigned int can rep-
resent all the values of the bit-field. If the bit-field is larger yet, no integral promotion applies to it. If the
bit-field has an enumerated type, it is treated as any other value of that type for promotion purposes.
An rvalue of type bool can be converted to an rvalue of type int, with false becoming zero and true
becoming one.
These conversions are called integral promotions.

4.5 积分提升[conv.prom]
如果 int 可以表示源类型的所有值,则可以将 char、signed char、unsigned char、short int 或 unsigned short int 类型的右值转换为 int 类型的右值;否则
,源右值可以转换为 unsigned int 类型的右值。
wchar_t (3.9.1) 类型或枚举类型 (7.2) 类型的右值可以转换为
以下第一种类型的右值,这些类型可以表示其基础类型的所有值:int、unsigned int、
long 或 unsigned长。
如果 int 可以表示
位域的所有值,则整型位域 (9.6) 的右值可以转换为 int 类型的右值;否则,如果 unsigned int 可以表示,则可以将其转换为 unsigned int
重新发送位域的所有值。如果位字段更大,则没有积分提升适用于它。如果
位字段具有枚举类型,则出于提升目的,将其视为该类型的任何其他值。
bool 类型的右值可以转换为 int 类型的右值,false 变为 0,true
变为 1。
这些转换称为积分促销。

4.6 Floating point promotion[conv.fpprom]
An rvalue of type float can be converted to an rvalue of type double. The value is unchanged.
This conversion is called floating point promotion.

4.6 浮点提升[conv.fpprom]
一个 float 类型的右值可以转换成一个 double 类型的右值。值不变。
这种转换称为浮点提升。

Therefore, all conversions involving float - the result is float.

因此,所有涉及浮点数的转换——结果都是浮点数。

Only the one involving both int - the result is int : int / int = int

只有一个同时涉及 int - 结果是 int : int / int = int

回答by B?ови?

Caveat!

警告!

The conversions occur from left to right.

转换从左到右发生。

Try this:

尝试这个:

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