C++ 中的隐式类型转换规则运营商

发布于 2024-10-30 02:37:29 字数 264 浏览 5 评论 0 原文

我想更好地知道何时应该施放。 C++ 中加法、乘法等时的隐式类型转换规则是什么。例如,

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

等等……

表达式是否总是被计算为更精确的类型? Java 的规则是否有所不同? 如果我对这个问题的措辞不准确,请纠正我。

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,

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

回忆追雨的时光 2024-11-06 02:37:29

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

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

笔记。操作的最小大小为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>

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).

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. So short/char are promoted to int before the operation is done.

In all your expressions the int is promoted to a float before the operation is performed. The result of the operation is a 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>
微暖i 2024-11-06 02:37:29

涉及 float 的算术运算结果为 float

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

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

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

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

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

——否则,如果有的话
操作数为 double,另一个为
转换为双精度。

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

— 否则,积分促销
(4.5) 应同时执行
操作数.54)

——那么,如果任一操作数
是无符号长,另一个应是
转换为无符号长整型。

——否则,如果一个操作数是一个长操作数
int 和另一个无符号 int,然后
如果一个long int可以代表所有
unsigned int 的值,
unsigned int 应转换为
长整型;否则两个操作数
应转换为 unsigned long
整数。

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

——否则,如果任一操作数
未签名的,其​​他应为
转换为无符号。

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

Arithmetic operations involving float results in 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

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 ]

一指流沙 2024-11-06 02:37:29

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

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

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

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

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

—否则,如果其中一个操作数是浮点型,则另一个操作数应转换为浮点型。

— 否则,将对两个操作数执行积分提升。那么以下规则应应用于提升的操作数:

<块引用>

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

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

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

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

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

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

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):

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.

See here for a list that's frequently updated.

ペ泪落弦音 2024-11-06 02:37:29

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

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

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

3) 该规定有时被称为“假设”规则,因为
实施可以自由地忽略标准的任何要求
只要结果就像满足了要求一样
这可以从程序的可观察行为中确定。

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

因此,在理论计算机具有超快 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

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

This answer is directed in large part at a comment made by @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?

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

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.

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.

Therefore, in the case of a theoretical computer with super-fast 8-bit operations, the implicit promotion to int for arithmetic could matter. 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.

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 + 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.

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

音栖息无 2024-11-06 02:37:29

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

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

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.)

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.)

行至春深 2024-11-06 02:37:29

我对解决方案 439/problem/B" rel="nofollow">问题得到了WA(错误答案),然后我将int之一更改为long long int,它给出了AC(接受)。之前,我尝试执行long long int += int * int,然后将其纠正为long long int += long long int * int。谷歌搜索我想出了,

1.算术转换

类型转换的条件:

满足条件--->转换

  • 任一操作数都是long double类型。 --->其他操作数转换为 long double 类型。

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

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

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

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

2. 整数转换规则

  • 整数提升:

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

  • 整数转换排名:

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

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

My solution to the problem got WA(wrong answer), then i changed one of int to long long int and 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,

1. Arithmetic Conversions

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 long and 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.

2 . Integer conversion rules

  • 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.

  • 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 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.
    • 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 char shall equal the rank of signed char and 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.
巡山小妖精 2024-11-06 02:37:29

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

4.5 积分促销
[会议舞会]
char、signed char、unsigned char、short int 或 unsigned Short 类型的右值
如果 int 可以表示源类型的所有值,则 int 可以转换为 int 类型的右值;其他-
明智的是,源右值可以转换为 unsigned int 类型的右值。
wchar_t 类型(3.9.1)或枚举类型(7.2)的右值可以转换为第一个的右值
以下类型可以表示其基础类型的所有值:int、unsigned int、
长整型或无符号长整型。
如果 int 可以表示所有,则整型位域 (9.6) 的右值可以转换为 int 类型的右值
位字段的值;否则,如果 unsigned int 可以表示,则可以转换为 unsigned int-
重新发送位字段的所有值。如果位域仍然较大,则不会对其应用积分提升。如果
位字段具有枚举类型,出于促销目的,它被视为该类型的任何其他值。
bool 类型的右值可以转换为 int 类型的右值,其中 false 为零,true
成为一体。
这些转换称为积分促销。

4.6 浮点提升
[转换.fprom]
float 类型的右值可以转换为 double 类型的右值。该值不变。
这种转换称为浮点提升。

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

只有同时涉及 int 的那个 - 结果是 int :
整数 / 整数 = 整数

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

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.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.

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

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

暖阳 2024-11-06 02:37:29

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

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

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

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.

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.

梦冥 2024-11-06 02:37:29

注意!

转换从左到右进行。

试试这个:

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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文