Есть ли разница между 0 и 0.0 в С++? Что вы должны использовать для инициализации двойника?
Спасибо
Есть ли разница между 0 и 0.0 в С++? Что вы должны использовать для инициализации двойника?
Спасибо
Литерал 0
считается литералом int
; литерал 0.0
является литералом double
. При назначении на double
будет работать любой из них (поскольку int
можно преобразовать в расширяющем преобразовании); однако приведение 0.0
к int
является сужающим преобразованием и должно выполняться явно; то есть (int)0.0
.
int a = 0.0;
.
- person Johannes Schaub - litb; 06.09.2009
Я стараюсь, чтобы мои константы соответствовали типам. 0 для целых. 0.0f или 0.f для float и 0.0 для double.
На мой взгляд, наиболее важной причиной для этого является то, что компилятор и программист видят одно и то же.
Если я сделаю это...
float t=0.5f;
float r;
r= 1 * t;
...должен ли быть присвоен r 0 или .5? Без колебаний, если я сделаю это вместо этого...
float t=0.5f;
float r;
r= 1.0f * t;
Один из них представляет собой целочисленный литерал, а другой — литерал с плавающей запятой. Для компилятора действительно не имеет значения, инициализируете ли вы числа с плавающей запятой или удвоения целочисленными литералами. В любом случае литерал будет скомпилирован в некоторое внутреннее представление.
Я бы предложил 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++ использует метод XOR-соединения регистра XMM с самим собой. Если бы вы сначала загрузили целое число 0, а затем переместили его в регистр XMM, потребовалась бы дополнительная инструкция. Учитывая нашу гипотезу о том, как 0.0
может быть загружен как литерал, а также дополнительную бесполезную загрузку инструкций, загружающую целое число 0, а затем перемещая его в регистр с плавающей запятой, ни один из них не является оптимальным, поэтому кажется, что это действительно не имеет значения. потому что автор компилятора, мы должны предположить, что эта оптимизация была известна в течение длительного времени, потому что она очевидна. Если требуется 100% переносимость, то более переносимым будет написать встроенную функцию, которая вручную использует метод XOR.