Owszem, kompilator poradzi sobie z dopasowaniem typu float<->double, ale to wcale nie znaczy, że 10.5 i 10.5f są równoważne, bo nie zawsze kompilator może dokonać konwersji bez efektów ubocznych (i czasami tej konwersji nie dokona). Poniżej kod Bar i Baz nie jest równoważny (bo nie powinien):
float Bar(float f)
{
return f * 11.45f;
}
float Baz(float f)
{
return f * 11.45;
}
int wmain(int argc, WCHAR *argv[])
{
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
float f1 = 10.512f;
float rf1 = Bar(f1);
float rf2 = Baz(f1);
wprintf(L"%f %f %f\n", f1, rf1, rf2);
return 0;
}
Jeśli ktoś ma wątpliwości, oto wynik z VC++:
__real@4026e66660000000 DQ 04026e66660000000r ; 11.45
...
?Bar@@YAMM@Z PROC ; Bar, COMDAT
...
fld DWORD PTR _f$[ebp]
fmul QWORD PTR __real@4026e66660000000
fstp DWORD PTR tv67[ebp]
fld DWORD PTR tv67[ebp]
...
__real@4026e66666666666 DQ 04026e66666666666r ; 11.45
...
?Baz@@YAMM@Z PROC ; Baz, COMDAT
...
fld DWORD PTR _f$[ebp]
fmul QWORD PTR __real@4026e66666666666
fstp DWORD PTR tv67[ebp]
fld DWORD PTR tv67[ebp]
Wyraźnie widać, że obie stałe mają odmienną precyzję, tak jak powinny. Dzieje się tak gdy na stałej wykonywana jest operacja arytmetyczna i może prowadzić do odmiennych wyników.
10.512000 120.362396 120.362404
W przypadku prostej inicjalizacji (przeważnie) nie ma problemu, ale pisanie “skąd taki pomysł, że 10.5 jest double?” świadczy o drobnych brakach w wiedzy. Zresztą w podanym wyżej przypadku, przy kompilacji z /W4, kompilator nie plułby się bez powodu, prawda?
warning C4244: 'return' : conversion from 'double' to 'float', possible loss of data