[英]Implicit type conversion rules in C++ operators
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?
Java 的规则是否不同? Please correct me if I have worded this question inaccurately.
如果我对这个问题的表述不准确,请纠正我。
In C++ operators (for POD types) always act on objects of the same type.在 C++ 运算符(用于 POD 类型)中,始终作用于相同类型的对象。
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).运算结果的类型与操作数相同(转换后)。
if:
either is long double other is promoted > long double
either is double other is promoted > double
either is float other is promoted > float
either is long long unsigned int other is promoted > long long unsigned int
either is long long int other is promoted > long long int
either is long unsigned int other is promoted > long unsigned int
either is long int other is promoted > long int
either is unsigned int other is promoted > unsigned int
either is int other is promoted > int
Otherwise:
both operands are promoted to int
Note.笔记。 The minimum size of operations is
int
.操作的最小大小是
int
。 So short
/ char
are promoted to int
before the operation is done.所以
short
/ char
在操作完成之前被提升为int
。
In all your expressions the int
is promoted to a float
before the operation is performed.在所有表达式中,
int
在执行操作之前被提升为float
。 The result of the operation is 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>
Arithmetic operations involving float
results 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 .
目的是产生一个通用类型,它也是 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.
— 如果任一操作数是 long double 类型,则另一个应转换为 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)
— 否则,应在两个操作数上执行积分提升 (4.5)。54)
— Then, if either operand is unsigned long the other shall be converted to unsigned long.
— 然后,如果任一操作数是 unsigned long,则另一个应转换为 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;
——否则,如果一个操作数是一个long int而另一个是unsigned int,那么如果一个long int可以表示一个unsigned int的所有值,那么这个unsigned int就应该被转换成一个long int; otherwise both operands shall be converted to unsigned long int.
否则两个操作数都应转换为 unsigned long int。
— Otherwise, if either operand is long, the other shall be converted to long.
— 否则,如果任一操作数为 long,则另一个应转换为 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 ]
[注意:否则,唯一剩下的情况是两个操作数都是 int ]
Since the other answers don't talk about the rules in C++11 here's one.由于其他答案没有讨论 C++11 中的规则,这里是一个。 From C++11 standard (draft n3337) §5/9 (emphasized the difference):
来自 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.
— 如果任一操作数是 long double 类型,则另一个应转换为 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.
— 否则,两个操作数都应转换为与带符号整数类型的操作数类型对应的无符号整数类型。
See here for a list that's frequently updated.请参阅此处获取经常更新的列表。
This answer is directed in large part at a comment made by @RafałDowgird:这个答案在很大程度上是针对@RafałDowgird 的评论:
"The minimum size of operations is int."
“操作的最小大小是 int。” - This would be very strange (what about architectures that efficiently support char/short operations?) Is this really in the C++ spec?
- 这会很奇怪(有效支持 char/short 操作的架构呢?)这真的在 C++ 规范中吗?
Keep in mind that the C++ standard has the all-important "as-if" rule.请记住,C++ 标准具有非常重要的“as-if”规则。 See section 1.8: Program Execution:
请参阅第 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 int
to be 8 bits in size, even if it were the fastest, since the standard mandates a 16-bit minimum int
.编译器不能将
int
大小设置为 8 位,即使它是最快的,因为标准要求最小为 16 位的int
。
Therefore, in the case of a theoretical computer with super-fast 8-bit operations, the implicit promotion to int
for arithmetic could matter.因此,在具有超快 8 位运算的理论计算机的情况下,隐式提升到
int
以进行算术运算可能很重要。 However, for many operations, you cannot tell if the compiler actually did the operations in the precision of an int
and then converted to a char
to store in your variable, or if the operations were done in char all along.但是,对于许多操作,您无法判断编译器是否确实以
int
的精度进行了操作,然后将其转换为char
以存储在您的变量中,或者这些操作是否一直在 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).例如,考虑
unsigned char = unsigned char + unsigned char + unsigned char
,其中加法会溢出(假设每个值为 200)。 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 + 200
to 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 int
if the operands have a lower ranking than int
.如果您升级为
int
,您将获得 600,然后将其隐式转换为unsigned char
,这将包装模 256,从而得到 88 的最终结果。如果您没有进行此类促销,则必须包装在前两个加法之间,将问题从200 + 200 + 200
到144 + 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.
对于除法或模数而言,通常情况并非如此。
If you exclude the unsigned types, there is an ordered hierarchy: signed char, short, int, long, long long, float, double, long double.如果排除无符号类型,则有一个有序的层次结构:signed char、short、int、long、long long、float、double、long double。 First, anything coming before int in the above will be converted to int.
首先,上面的 int 之前的任何内容都将转换为 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.)
(您会注意到,从层次结构中,只要涉及浮点类型和整数类型,整数类型就会转换为浮点类型。)
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 推荐的。)
My solution to the problem got WA(wrong answer), then i changed one of int
to long long int
and it gave AC(accept) .我对问题的解决方案得到了 WA(错误答案),然后我将
int
之一更改为long long int
并给出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
.以前,我试图做
long long int += int * int
,在我将其纠正为long long int += long long int * int
。 Googling I came up with,我想出的谷歌搜索,
Conditions for Type Conversion:类型转换的条件:
Conditions Met ---> Conversion满足条件 ---> 转换
Either operand is of type long double .任一操作数的类型为long double 。 ---> Other operand is converted to type long double .
---> 其他操作数转换为long double类型。
Preceding condition not met and either operand is of type double .不满足前面的条件,并且任一操作数的类型为double 。 ---> Other operand is converted to type double .
---> 其他操作数转换为double类型。
Preceding conditions not met and either operand is of type float .不满足前面的条件,并且任一操作数的类型为float 。 ---> Other operand is converted to type float .
---> 其他操作数转换为float类型。
Preceding conditions not met (none of the operands are of floating types).不满足前面的条件(所有操作数都不是浮点类型)。 ---> Integral promotions are performed on the operands as follows:
---> 对操作数执行积分提升如下:
Integer types smaller than int are promoted when an operation is performed on them.当对它们执行操作时,会提升小于 int 的整数类型。 If all values of the original type can be represented as an int, the value of the smaller type is converted to an int;
如果原始类型的所有值都可以表示为int,则将较小类型的值转换为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.
和移位运算符的操作数。
Integer Conversion Rank:整数转换等级:
long long int
shall 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
.long long int
应大于军衔更高的long int
,这应该比军衔更高的int
,这应该比军衔更高的short int
,这应该比军衔更高的signed char
。char
shall equal the rank of signed char
and unsigned char
. char
的等级应等于signed char
和unsigned char
的等级。 Usual Arithmetic Conversions:通常的算术转换:
The type of the expression, when not both parts are of the same type, will be converted to the biggest of 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 类型。
Whole chapter 4 talks about conversions, but I think you should be mostly interested in these :整个第 4 章都在讨论转换,但我认为您应该对这些最感兴趣:
4.5 Integral promotions [conv.prom] 4.5 积分促销[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;如果 int 可以表示源类型的所有值,则 char、signed char、unsigned char、short int 或 unsigned short int 类型的右值可以转换为 int 类型的右值; other-
其他-
wise, the source rvalue can be converted to an rvalue of type unsigned int.明智的做法是,源右值可以转换为 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类型 wchar_t (3.9.1) 或枚举类型 (7.2) 的右值可以转换为第一个的右值
of the following types that can represent all the values of its underlying type: int, unsigned int,以下类型可以表示其基础类型的所有值: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如果 int 可以表示所有,则整数位域 (9.6) 的右值可以转换为 int 类型的右值
the values of the bit-field;位域的值; otherwise, it can be converted to unsigned int if unsigned int can rep-
否则,如果 unsigned int 可以表示,则可以将其转换为 unsigned int
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 bool 类型的右值可以转换为 int 类型的右值,false 变为 0 和 true
becoming one.成为一。
These conversions are called integral promotions.这些转换称为积分促销。
4.6 Floating point promotion [conv.fpprom] 4.6 浮点提升【conv.fpprom】
An rvalue of type float can be converted to an rvalue of type double. float 类型的右值可以转换为 double 类型的右值。 The value is unchanged.
值不变。
This conversion is called floating point promotion.这种转换称为浮点提升。
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
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.