我想知道什么时候应该投出更好。在添加,乘法等时,C ++中的隐式类型转换规则是什么。例如,
int + float = ?
int * float = ?
float * int = ?
int / float = ?
float / int = ?
int / int = ?
int ^ float = ?
等等......
表达式是否总是被评估为更精确的类型? Java的规则有所不同吗? 如果我不准确地说出这个问题,请纠正我。
答案 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
之后。谷歌搜索我想出来,
类型转换的条件:
条件符合---&gt;转化
任一操作数的类型为 long double 。 ---&GT;其他操作数转换为 long double 类型。
未满足前置条件且任一操作数的类型为 double 。 ---&GT;其他操作数转换为 double 类型。
未满足前面的条件且任一操作数的类型为 float 。 ---&GT;其他操作数转换为 float 类型。
未满足前置条件(没有任何操作数属于浮点类型)。 ---&GT;对操作数执行整体促销,如下所示:
对它们执行操作时,会提升小于int的整数类型。如果原始类型的所有值都可以表示为int,则较小类型的值将转换为int;否则,它将转换为unsigned int。整数促销作为通常算术转换的一部分应用于某些参数表达式;一元+, - 和〜运算符的操作数;移位运营商的操作和操作。
整数转换排名:
long long int
的排名应大于long int
的排名,int
的排名应大于short int
的排名,signed char
的排名应大于char
的排名},应大于signed char
的等级。unsigned char
的等级应等于{{1}}和{{1}}的等级。通常的算术转换:
答案 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