Reputation:
Is there a difference between 0 and 0.0 in C++? Which should you use for initializing a double?
Thanks
Upvotes: 21
Views: 45394
Reputation:
Here is the Visual-C++ disassembly for:
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
They produced the same assembly. Visual-C++ uses the method of XOR-ing the XMM register with it'self. Had you first loaded the integer 0 then moved it into the XMM register it would have used an extra instruction. Given our hypothesis on how the 0.0
may be loaded as a literal, as well as the extra useless instruction load loading an integer 0 then moving it into a floating-point register, neither is optimal so it seems as though it really doesn't matter because the compiler writer we must assume this optimization has been know for a long time because it is kind of obvious. If 100% portability is required, then it is more portable to write an inline function that manually uses the XOR technique.
Upvotes: 3
Reputation: 86326
I try to keep my constants type-consistent. 0 for ints. 0.0f or 0.f for float, and 0.0 for double.
To me, the most important reason to do this is so the compiler and the programmer see the same thing.
If I do this...
float t=0.5f;
float r;
r= 1 * t;
...should r be assigned 0 or .5? There's no hesitation if I do this instead...
float t=0.5f;
float r;
r= 1.0f * t;
Upvotes: 13
Reputation: 17520
One appears to be an integer literal, the other a floating point literal. It really doesn't matter to the compiler whether you initialize floats or doubles with integer literals. In any event the literal will be compiled into some internal representation.
I would tend to suggest 0.0 in order to make your intention (to other programmers) explicitly clear.
Upvotes: 6
Reputation: 48377
A literal 0
is considered to be an int
literal; literal 0.0
is a double
literal. When assigning to a double
, either will work (since the int
can be cast in a widening conversion); however, casting 0.0
to an int
is a narrowing conversion, and must be done explicitly; i.e. (int)0.0
.
Upvotes: 23