いつキャストすべきかを知りたい。追加、乗算などを行うときのC++の暗黙の型変換規則は何ですか。たとえば、
int + float = ?
int * float = ?
float * int = ?
int / float = ?
float / int = ?
int / int = ?
int ^ float = ?
など.
式は常により正確な型として評価されますか? Javaのルールは異なりますか?この質問を不正確に言った場合は修正してください。
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>
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に変換されます。
—それ以外の場合、一方のオペランドがfloatであれば、他方はfloatに変換されます。
—それ以外の場合、両方のオペランドで積分プロモーション(4.5)が実行されます。54)
—次に、一方のオペランドが符号なしlongの場合、他方は符号なしlongに変換されます。
—それ以外の場合、一方のオペランドがlong intで、もう一方がunsigned intであり、long intがunsigned intのすべての値を表すことができる場合、unsigned intはlong intに変換されます。それ以外の場合、両方のオペランドは符号なしlong intに変換されます。
—それ以外の場合、一方のオペランドが長い場合、他方はlongに変換されます。
—それ以外の場合、一方のオペランドが符号なしの場合、他方は符号なしに変換されます。
[注:それ以外の場合、残っているのは両方のオペランドがintである場合のみです]
他の回答ではC++ 11のルールについて説明していないため、ここに1つあります。 C++ 11標準(ドラフトn3337)§5/ 9から:
このパターンは、通常の算術変換と呼ばれ、次のように定義されます。
—いずれかのオペランドがスコープ付き列挙型の場合、変換は実行されません。他のオペランドの型が同じでない場合、式の形式は正しくありません。
—どちらかのオペランドがlong double型の場合、もう一方はlong doubleに変換されます。
—それ以外の場合、一方のオペランドがdoubleであれば、他方はdoubleに変換されます。
—それ以外の場合、一方のオペランドがfloatであれば、他方はfloatに変換されます。
—それ以外の場合、積分プロモーションは両方のオペランドで実行されます。次に、昇格されたオペランドに次の規則が適用されます。
—両方のオペランドの型が同じ場合、それ以上の変換は不要です。
—それ以外の場合、両方のオペランドに符号付き整数型があるか、両方に符号なし整数型がある場合、整数変換ランクが小さい型のオペランドは、ランクが大きいオペランドの型に変換されます。
—それ以外の場合、符号なし整数型のオペランドのランクが他のオペランドの型のランク以上である場合、符号付き整数型のオペランドは符号なし整数型のオペランドの型に変換されます。
—それ以外の場合、符号付き整数型のオペランドの型が符号なし整数型のオペランドの型のすべての値を表すことができる場合、符号なし整数型のオペランドは符号付き整数型のオペランドの型に変換されます。
—それ以外の場合、両方のオペランドは、符号付き整数型のオペランドの型に対応する符号なし整数型に変換されます。
頻繁に更新されるリストについては、 here をご覧ください。
この回答の大部分は、@RafałDowgirdによるコメントに向けられています。
「操作の最小サイズはintです。」 -これは非常に奇妙です(char/short操作を効率的にサポートするアーキテクチャはどうですか?)これは本当にC++仕様にありますか?
C++標準には非常に重要な「as-if」ルールがあることに注意してください。セクション1.8:プログラムの実行を参照してください:
3)この規定は、「as-if」ルールと呼ばれることもあります。実装は、観察可能なものから判断できる限り、結果が要件に従っている限り、標準の要件を自由に無視できるためです。プログラムの動作。
標準では16ビットの最小int
が義務付けられているため、コンパイラはint
を8ビットのサイズに設定することはできません。
したがって、超高速8ビット演算を備えた理論的なコンピューターの場合、算術演算のint
への暗黙的な昇格が重要になる可能性があります。ただし、多くの操作では、コンパイラが実際にint
の精度で操作を実行し、変数に格納するためにchar
に変換されたかどうか、または操作がcharで実行されたかどうかはわかりませんずっと。
例えば、加算がオーバーフローするunsigned char = unsigned char + unsigned char + unsigned char
を考えてみましょう(それぞれ200の値を想定しましょう)。 int
に昇格すると、600が得られます。これは暗黙的にunsigned char
にダウンキャストされ、256を法としてラップするため、88の最終結果が得られます。 、最初の2つの追加の間にラップする必要があります。これにより、問題が200 + 200 + 200
から144 + 200
(344)に減少し、88に減少します。つまり、プログラムはそのため、コンパイラーは、オペランドがint
より低いランキングを持っている場合、int
で中間操作を実行するという命令を自由に無視できます。
これは、加算、減算、および乗算の一般に当てはまります。一般に、除算またはモジュラスには当てはまりません。
符号なしの型を除外すると、順序付きの階層があります:signed char、short、int、long、long long、float、double、long double。最初に、上記のintの前に来るものはすべてintに変換されます。次に、2項演算では、低いランクの型が高い型に変換され、結果は高い型になります。 (階層から、浮動小数点と整数型が関係する場合は常に、整数型が浮動小数点型に変換されることに注意してください。)
符号なしは、少し物事を複雑にします。それはランキングを混乱させ、ランキングの一部が実装定義になります。このため、同じ式に符号付きと符号なしを混在させないことが最善です。 (ほとんどのC++エキスパートは、ビット単位の操作が関与しない限り、符号なしを回避しているようです。少なくとも、Stroustrupが推奨することです。)
ソリューション に対する 問題 はWA(間違った答え)を取得し、int
の1つをlong long int
に変更し、 AC(accept) 。以前は、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
のランクと等しくなります。通常の算術変換:
式の型は、両方の部分が同じ型ではない場合、両方のbiggestに変換されます。ここでの問題は、どちらがもう一方よりも大きいかを理解することです(バイト単位のサイズとは関係ありません)。
実数と整数が関係する式では、整数は実数に昇格されます。たとえば、int + floatでは、式のタイプはfloatです。
その他の違いは、タイプの機能に関連しています。たとえば、intとlong intを含む式は、long int型になります。
第4章全体でコンバージョンについて説明していますが、これらに最も興味があるはずです。
4.5インテグラルプロモーション [conv.prom]
char型、signed char型、unsigned char型、short int型、またはunsigned short int型の右辺値は、intがソース型のすべての値を表すことができる場合、int型の右辺値に変換できます。その他
賢明なことに、ソースの右辺値は、unsigned int型の右辺値に変換できます。
wchar_t型(3.9.1)または列挙型(7.2)の右辺値は、最初の右辺値に変換できます。
基本型のすべての値を表すことができる次の型:int、unsigned int、
long、またはunsigned long。
intがすべてを表現できる場合、整数ビットフィールド(9.6)の右辺値は、int型の右辺値に変換できます。
ビットフィールドの値。それ以外の場合は、unsigned intが繰り返し可能な場合、unsigned intに変換できます。
ビットフィールドのすべての値を再送信します。ビットフィールドがまだ大きい場合、統合的なプロモーションは適用されません。もし
ビットフィールドには列挙型があり、昇格のためにその型の他の値として扱われます。
bool型の右辺値は、int型の右辺値に変換できます。falseはゼロになり、trueになります
1つになります。
これらのコンバージョンは、インテグラルプロモーションと呼ばれます。
4.6浮動小数点の昇格 [conv.fpprom]
float型の右辺値は、double型の右辺値に変換できます。値は変更されません。
この変換は、浮動小数点プロモーションと呼ばれます。
したがって、floatを含むすべての変換-結果はfloatです。
両方のintを含むもののみ-結果はintです:int/int = int