いつキャストすればいいのかよく知りたいです。追加、乗算などの際の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で異なりますか?この質問の文言が不正確だった場合は訂正してください。
回答:
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>
char
タイプを使用できます。の値char + char
がに割り当てられているchar
場合は、算術演算を実行しchar
て、たとえばラップアラウンドすることができます。しかし、結果がに割り当てられている場合はint
、それがより大きい場合に正しい結果を得るのに十分な大きさの型で算術を実行する必要がありますCHAR_MAX
。
((int) 4) - ((unsigned int) 5)
になります4294967295
32ビットのint型と32ビット符号なし整数型のため。
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)
—次に、一方のオペランドがunsigned longの場合、もう一方はunsigned longに変換されます。
それ以外の場合、一方のオペランドが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の規則について話していないので、ここに1つあります。C ++ 11標準(ドラフトn3337)§5/ 9(違いを強調)から:
このパターンは通常の算術変換と呼ばれ、次のように定義されます。
—いずれかのオペランドがスコープ付き列挙型である場合、変換は実行されません。他のオペランドが同じ型でない場合、式の形式は正しくありません。
—どちらかのオペランドがlong double型の場合、もう一方はlong doubleに変換されます。
—そうでない場合、一方のオペランドがdoubleの場合、もう一方はdoubleに変換されます。
—それ以外の場合、一方のオペランドが浮動小数点数の場合、もう一方は浮動小数点数に変換されます。
—それ以外の場合、整数の昇格は両方のオペランドで実行されます。次に、昇格されたオペランドに次のルールが適用されます。
—両方のオペランドが同じタイプの場合、それ以上の変換は必要ありません。
—そうでない場合、両方のオペランドが符号付き整数型または両方が符号なし整数型を持つ場合、整数変換ランクの小さいタイプのオペランドは、ランクの大きいオペランドのタイプに変換されます。
—それ以外の場合、符号なし整数型のオペランドのランクが他のオペランドの型のランク以上である場合、符号付き整数型のオペランドは、符号なし整数型のオペランドの型に変換されます。
—それ以外の場合、符号付き整数型のオペランドの型が符号なし整数型のオペランドの型のすべての値を表すことができる場合、符号なし整数型のオペランドは符号付き整数型のオペランドの型に変換されます。
—そうでない場合、両方のオペランドは、符号付き整数型のオペランドの型に対応する符号なし整数型に変換されます。
頻繁に更新されるリストについては、こちらをご覧ください。
この回答は、主に@RafałDowgirdのコメントに向けられています。
「操作の最小サイズはintです。」-これは非常に奇妙です(char / short操作を効率的にサポートするアーキテクチャーについてはどうですか?)これは本当にC ++仕様にありますか?
C ++標準には非常に重要な「as-if」ルールがあることに注意してください。セクション1.8:プログラムの実行を参照してください。
3)この規定は、「as-if」ルールと呼ばれることもあります。これは、観察可能な結果から判断できる限り、実装は、結果が要件に準拠しているかのようである限り、標準の要件を無視してかまわないためです。プログラムの動作。
int
標準では16ビットの最小値が義務付けられているため、最速の場合でも、コンパイラはを8ビットのサイズに設定できませんint
。
したがって、超高速の8ビット演算を備えた理論上のコンピュータの場合、int
算術演算への暗黙の昇格が重要になる可能性があります。ただし、多くの操作では、コンパイラーが実際にanの精度で操作を行ってから変数に格納int
するためにa 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
。
これは、加算、減算、乗算の一般に当てはまります。除算や係数については、一般的には当てはまりません。
符号なしの型を除外する場合、順序付きの階層があります。signedchar、short、int、long、long long、float、double、long double。まず、上記のintの前に来るものはすべてintに変換されます。次に、2項演算では、ランクの低い型が上位の型に変換され、結果は上位の型になります。(階層から、浮動小数点と整数型が関係する場合は常に、整数型は浮動小数点型に変換されることに注意してください。)
符号なしは少し複雑になります:ランキングを混乱させ、ランキングの一部は実装定義になります。このため、同じ式で符号付きと符号なしを混在させないことをお勧めします。(ほとんどのC ++エキスパートは、ビット単位の演算が含まれていない限り、符号なしを避けているようです。それが、少なくとも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;
と、あなたは、サイズ()ので、それは空のベクトルのためにクラッシュしたことを見つけるために悩まされるだろう- 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]
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長いです。
整数ビットフィールド(9.6)の右辺値は、intが
ビットフィールドのすべての値を表すことができる場合、int型の右辺値に変換できます。それ以外の場合、unsigned intがrep-を実行できる場合は、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 は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 であることに注意してください。