我想更好地知道应该何时施展。加,乘等时,C ++中的隐式类型转换规则是什么。例如,
int + float = ?
int * float = ?
float * int = ?
int / float = ?
float / int = ?
int / int = ?
int ^ float = ?
等等...
表达式始终会被评估为更精确的类型吗?Java的规则是否有所不同?如果我对这个问题的措词不正确,请纠正我。
我想更好地知道应该何时施展。加,乘等时,C ++中的隐式类型转换规则是什么。例如,
int + float = ?
int * float = ?
float * int = ?
int / float = ?
float / int = ?
int / int = ?
int ^ float = ?
等等...
表达式始终会被评估为更精确的类型吗?Java的规则是否有所不同?如果我对这个问题的措词不正确,请纠正我。
Answers:
在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
其提升为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>
char
类型。如果将的值char + char
分配给char
,则它可以进行算术运算,char
例如环绕。但是,如果将结果分配给,int
则它必须以足够大的类型进行算术运算,以得到大于时的正确结果CHAR_MAX
。
((int) 4) - ((unsigned int) 5)
将导致4294967295
32位int和32位unsigned int。
涉及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,则另一个应转换为long double。
—否则,如果其中一个操作数为double,则另一个应转换为double。
—否则,如果其中一个操作数为浮点数,则另一个应转换为浮点数。
—否则,应在两个操作数上执行积分提升(4.5)(54)。
—然后,如果其中一个操作数为无符号长,则另一个应转换为无符号长。
—否则,如果一个操作数是long int,另一个操作数是unsigned int,则如果long int可以表示unsigned int的所有值,则将unsigned int转换为long int。否则,两个操作数均应转换为unsigned long int。
—否则,如果其中一个操作数为long,则另一个应转换为long。
—否则,如果一个操作数是无符号的,则另一个应转换为无符号。
[注意:否则,唯一剩下的情况是两个操作数都为int]
double
是long double
。
long long
和unsigned long
没有解决在这里。
由于其他答案不涉及C ++ 11中的规则,因此这里是一个。根据C ++ 11标准(n3337草案)§5/ 9(强调了区别):
这种模式称为通常的算术转换,其定义如下:
—如果任一操作数属于范围枚举类型,则不执行任何转换;否则,将不执行任何转换。如果另一个操作数的类型不同,则该表达式的格式不正确。
—如果一个操作数的类型为long double,则另一个应转换为long double。
—否则,如果其中一个操作数为double,则另一个应转换为double。
—否则,如果其中一个操作数为浮点数,则另一个应转换为浮点数。
—否则,应在两个操作数上执行积分提升。然后,将以下规则应用于提升后的操作数:
—如果两个操作数具有相同的类型,则无需进一步转换。
—否则,如果两个操作数都具有符号整数类型或都具有无符号整数类型,则应将具有较小整数转换等级的操作数转换为具有较大等级的操作数的类型。
—否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的秩,则带符号整数类型的操作数应转换为无符号整数类型的操作数的类型。
—否则,如果带符号整数类型的操作数的类型可以表示无符号整数类型的操作数的所有值,则应将无符号整数类型的操作数转换为带符号整数类型的操作数的类型。
—否则,两个操作数均应转换为与带符号整数类型的操作数类型相对应的无符号整数类型。
请参阅此处以获取经常更新的列表。
这个答案主要针对@RafałDowgird的评论:
“最小操作数为int。” -这很奇怪(有效支持char / short操作的体系结构是什么?)这真的在C ++规范中吗?
请记住,C ++标准具有非常重要的“假设”规则。请参见第1.8节:程序执行:
3)这项规定有时称为“按原样”规则,因为只要可以从可观察的范围内确定结果,就可以无视标准的任何要求,而该实现可以自由地执行程序的行为。
int
即使编译器最快,也不能将其设置为8位,因为该标准要求最小为16位int
。
因此,在理论计算机具有超快8位运算的情况下,int
对算术的隐式提升可能很重要。但是,对于许多操作,您无法确定编译器是否实际上以an的精度执行了这些操作int
,然后将其转换为a 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
。
通常,加法,减法和乘法都是如此。通常,除数或模数不是正确的。
如果排除无符号类型,则有一个有序的层次结构:带符号的char,short,int,long,long long,float,double,long double。首先,上述int之前的所有内容都将转换为int。然后,在二进制操作中,排名较低的类型将转换为较高的类型,结果将是较高的类型。(您会注意到,从层次结构中,每当涉及浮点和整数类型时,整数类型都会转换为浮点类型。)
Unsigned使事情变得有些复杂:它扰乱了排名,并且排名的一部分变成了实现定义。因此,最好不要在同一个表达式中混合使用带符号和无符号。(除非涉及到按位运算,否则大多数C ++专家似乎都避免使用unsigned。至少,这是Stroustrup建议的。)
int
对于永不为负的数字使用可签名的符号,则完全浪费了可用范围的50%。我当然不是Stroustrup,但我unsigned
默认使用,并且signed
仅在有理由的情况下使用。
bool in_order(vector<T> vec) { for ( int i = 0; i < size() - 1; ++i) { if (vec[i + 1] < vec[i]) return false; } return true;
,然后会发现它因空向量而崩溃,因为size()-1返回18446744073709551615。–
我对问题的解决方法是WA(错误答案),然后我将其中一个更改int
为long long int
,它给了AC(接受)。以前,我尝试这样做long long int += int * int
,然后将其更正为long long int += long long int * int
。我想出了谷歌搜索,
类型转换的条件:
满足条件--->转换
两种操作数都属于long double类型。--->其他操作数被转换为long double类型。
不满足前述条件,并且任何一个操作数均为double类型。--->其他操作数将转换为double类型。
不满足前述条件,并且两个操作数均为float类型。--->其他操作数将转换为float类型。
之前的条件不满足(所有操作数都不是浮点类型)。--->积分提升对操作数执行如下:
当对它们执行运算时,会提升小于int的整数类型。如果原始类型的所有值都可以表示为int,则较小类型的值将转换为int;否则,将其转换为unsigned int。整数提升作为常规算术转换的一部分应用于某些参数表达式;一元+,-和〜运算符的操作数;和移位运算符的操作数。
整数转换排名:
long long int
应大于的等级long int
,后者应大于的等级int
,后者的等级应大于的等级short int
,等级应大于的等级signed char
。char
应等于的秩signed char
和unsigned char
。通常的算术转换:
第4章讨论了转换,但是我认为您应该对转换最感兴趣:
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)的rvalue转换为int类型的rvalue 。否则,如果unsigned int可以表示-,则可以将其转换为unsigned int。
重新发送该位字段的所有值。如果位字段更大,则不应用整数提升。如果
位字段具有枚举类型,则出于提升目的将其视为该类型的任何其他值。
bool类型的右值可以转换为int类型的右值,false变为零,true
变为1。
这些转换称为整体促销。
4.6浮点数提升
[conv.fpprom]
float类型的右值可以转换为double类型的右值。该值不变。
这种转换称为浮点升级。
因此,所有涉及float的转换-结果都是float。
只有一个包含两个int的整数-结果是int:int / int = int
如果表达式的类型不是两个部分都属于同一类型,则将其转换为两者中最大的一个。这里的问题是要了解哪一个大于另一个(它与字节大小无关)。
在涉及实数和整数的表达式中,整数将提升为实数。例如,在int + float中,表达式的类型为float。
另一个区别与类型的能力有关。例如,一个包含int和long int的表达式将产生long int类型的结果。
long
比a“大”,float
但是long
+ 的类型是float
什么?
警告!
转换从左到右发生。
试试这个:
int i = 3, j = 2;
double k = 33;
cout << k * j / i << endl; // prints 22
cout << j / i * k << endl; // prints 0
j + i * k
会导致101
^
是XOR。