C++で0と0.0の間に違いはありますか?ダブルを初期化するためにどちらを使用する必要がありますか?
ありがとう
リテラル0
はint
リテラルと見なされます。リテラル0.0
はdouble
リテラルです。 double
に割り当てる場合、どちらも機能します(int
は拡大変換でキャストできるため)。ただし、キャスト0.0
からint
への変換は絞り込み変換であり、明示的に実行する必要があります。つまり、(int)0.0
。
定数の型の一貫性を保つようにしています。 intsの場合は0。フロートの場合は0.0fまたは0.f、ダブルの場合は0.0。
私にとって、これを行う最も重要な理由は、コンパイラーとプログラマーが同じことを理解できるようにするためです。
私がこれをするなら...
float t=0.5f;
float r;
r= 1 * t;
... rには0または.5を割り当てる必要がありますか?代わりにこれを行うのであれば、ためらうことはありません...
float t=0.5f;
float r;
r= 1.0f * t;
1つは整数リテラルのように見え、もう1つは浮動小数点リテラルのように見えます。 floatを初期化するか、整数リテラルでdoubleを初期化するかは、コンパイラにとって実際には重要ではありません。いずれにせよ、リテラルは何らかの内部表現にコンパイルされます。
(他のプログラマーに)あなたの意図を明確にするために、0.0を提案する傾向があります。
Visual-C++の逆アセンブリは次のとおりです。
int main() {
double x = 0;
//
double y = 0.0;
//
double z = x * y;
return 0;
}
int main() {
00007FF758A32230 Push rbp
00007FF758A32232 Push rdi
00007FF758A32233 sub rsp,128h
00007FF758A3223A mov rbp,rsp
00007FF758A3223D mov rdi,rsp
00007FF758A32240 mov ecx,4Ah
00007FF758A32245 mov eax,0CCCCCCCCh
00007FF758A3224A rep stos dword ptr [rdi]
double x = 0;
00007FF758A3224C xorps xmm0,xmm0
00007FF758A3224F movsd mmword ptr [x],xmm0
//
double y = 0.0;
00007FF758A32254 xorps xmm0,xmm0
00007FF758A32257 movsd mmword ptr [y],xmm0
//
double z = x * y;
00007FF758A3225C movsd xmm0,mmword ptr [x]
00007FF758A32261 mulsd xmm0,mmword ptr [y]
00007FF758A32266 movsd mmword ptr [z],xmm0
return 0;
00007FF758A3226B xor eax,eax
}
00007FF758A3226D lea rsp,[rbp+128h]
00007FF758A32274 pop rdi
00007FF758A32275 pop rbp
00007FF758A32276 ret
彼らは同じアセンブリを作成しました。 Visual-C++は、XMMレジスタをそれ自体とXORする方法を使用します。最初に整数0をロードしてから、それをXMMレジスタに移動した場合、追加の命令が使用されます。どのように0.0
はリテラルとしてロードされる可能性があり、整数0をロードして浮動小数点レジスタに移動する余分な無用な命令ロードも最適ではないため、コンパイラの作成者であるため、実際には問題ではないようです。この最適化は明らかであるため、長い間知られていると想定する必要があります。 100%の移植性が必要な場合は、XOR手法を手動で使用するインライン関数を作成する方が移植性が高くなります。