看一看这个例子:Visual Studio中调试与发布版本:比较int和float missmatch
#include <stdio.h>
int main() {
int i= 16777217;
float f = 16777216.0;
float g = i;
if(i == f)
printf("eq\n");
else
printf("neq\n");
if(g == f)
printf("eq\n");
else
printf("neq\n");
return 0;
}
其中,使用Visual Studio 2010 C++(VS)在释放模式,GCC,或g ++(4.9 0.2),具有输出
eq
eq
这是合理的,我:在第一比较,i
隐式转换为其中在尾数的显著位被截断的浮子。因此,i
和f
都具有相同的比较模式。在第二个if
中,应用了相同的转换,但在定义和初始化g
时已执行。
然而,在调试模式下使用VS,其结果是
neq
eq
看来,在第一if
比较(如在C和C通常的算术转换++的一部分)中的隐式转换不被施加。这是真的?有没有一种VS机制可以在比较浮点数和整数(更精确地转换为int/float)时防止这种误报?根据MSDN VS C++遵循标准。
我已经检查了位表示与this function。对于所有的编译器它产生对VS
i = 00000001000000000000000000000001
f = 01001011100000000000000000000000
g = 01001011100000000000000000000000
float.h
指出#define FLT_MANT_DIG 24
这样描述截断问题应持有为好。
我编译所有在同一台机器上(英特尔i5-3570K),但VS在一个虚拟的盒子。在另一台机器上编译VS也会打印neq/eq
。
编辑:汇编代码附加
differences_debug.asm
; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.30319.01
TITLE c:\Users\user\documents\visual studio 2010\Projects\differences\differences\differences.cpp
.686P
.XMM
include listing.inc
.model flat
INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES
PUBLIC [email protected][email protected][email protected] ; `string'
PUBLIC [email protected][email protected][email protected] ; `string'
PUBLIC [email protected]
PUBLIC _wmain
EXTRN __imp__printf:PROC
EXTRN __fltused:DWORD
EXTRN __RTC_CheckEsp:PROC
EXTRN __RTC_Shutdown:PROC
EXTRN __RTC_InitBase:PROC
; COMDAT [email protected][email protected][email protected]
; File c:\users\user\documents\visual studio 2010\projects\differences\differences\differences.cpp
CONST SEGMENT
[email protected][email protected][email protected] DB 'neq', 0aH, 00H ; `string'
CONST ENDS
; COMDAT [email protected][email protected][email protected]
CONST SEGMENT
[email protected][email protected][email protected] DB 'eq', 0aH, 00H ; `string'
CONST ENDS
; COMDAT [email protected]
CONST SEGMENT
[email protected] DD 04b800000r ; 1.67772e+007
CONST ENDS
; COMDAT rtc$TMZ
rtc$TMZ SEGMENT
__RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown
rtc$TMZ ENDS
; COMDAT rtc$IMZ
rtc$IMZ SEGMENT
__RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase
; Function compile flags: /Odtp /RTCsu /ZI
rtc$IMZ ENDS
; COMDAT _wmain
_TEXT SEGMENT
_g$ = -32 ; size = 4
_f$ = -20 ; size = 4
_i$ = -8 ; size = 4
_argc$ = 8 ; size = 4
_argv$ = 12 ; size = 4
_wmain PROC ; COMDAT
; Line 7
push ebp
mov ebp, esp
sub esp, 228 ; 000000e4H
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-228]
mov ecx, 57 ; 00000039H
mov eax, -858993460 ; ccccccccH
rep stosd
; Line 8
mov DWORD PTR _i$[ebp], 16777217 ; 01000001H
; Line 9
fld DWORD PTR [email protected]
fstp DWORD PTR _f$[ebp]
; Line 10
fild DWORD PTR _i$[ebp]
fstp DWORD PTR _g$[ebp]
; Line 13
fild DWORD PTR _i$[ebp]
fld DWORD PTR _f$[ebp]
fucompp
fnstsw ax
test ah, 68 ; 00000044H
jp SHORT [email protected]
; Line 14
mov esi, esp
push OFFSET [email protected][email protected][email protected]
call DWORD PTR __imp__printf
add esp, 4
cmp esi, esp
call __RTC_CheckEsp
; Line 15
jmp SHORT [email protected]
[email protected]:
; Line 16
mov esi, esp
push OFFSET [email protected][email protected][email protected]
call DWORD PTR __imp__printf
add esp, 4
cmp esi, esp
call __RTC_CheckEsp
[email protected]:
; Line 19
fld DWORD PTR _g$[ebp]
fld DWORD PTR _f$[ebp]
fucompp
fnstsw ax
test ah, 68 ; 00000044H
jp SHORT [email protected]
; Line 20
mov esi, esp
push OFFSET [email protected][email protected][email protected]
call DWORD PTR __imp__printf
add esp, 4
cmp esi, esp
call __RTC_CheckEsp
; Line 21
jmp SHORT [email protected]
[email protected]:
; Line 22
mov esi, esp
push OFFSET [email protected][email protected][email protected]
call DWORD PTR __imp__printf
add esp, 4
cmp esi, esp
call __RTC_CheckEsp
[email protected]:
; Line 24
xor eax, eax
; Line 26
pop edi
pop esi
pop ebx
add esp, 228 ; 000000e4H
cmp ebp, esp
call __RTC_CheckEsp
mov esp, ebp
pop ebp
ret 0
_wmain ENDP
_TEXT ENDS
END
differences_release.asm
; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.30319.01
TITLE c:\Users\user\documents\visual studio 2010\Projects\differences\differences\differences.cpp
.686P
.XMM
include listing.inc
.model flat
INCLUDELIB OLDNAMES
PUBLIC [email protected][email protected][email protected] ; `string'
PUBLIC [email protected][email protected][email protected] ; `string'
EXTRN @[email protected]:PROC
EXTRN __imp__printf:PROC
; COMDAT [email protected][email protected][email protected]
CONST SEGMENT
[email protected][email protected][email protected] DB 'neq', 0aH, 00H ; `string'
CONST ENDS
; COMDAT [email protected][email protected][email protected]
CONST SEGMENT
[email protected][email protected][email protected] DB 'eq', 0aH, 00H ; `string'
CONST ENDS
PUBLIC _wmain
EXTRN __fltused:DWORD
; Function compile flags: /Ogtp
; COMDAT _wmain
_TEXT SEGMENT
_argc$ = 8 ; size = 4
_argv$ = 12 ; size = 4
_wmain PROC ; COMDAT
; File c:\users\user\documents\visual studio 2010\projects\differences\differences\differences.cpp
; Line 7
push esi
; Line 14
mov esi, DWORD PTR __imp__printf
push OFFSET [email protected][email protected][email protected]
call esi
; Line 20
push OFFSET [email protected][email protected][email protected]
call esi
add esp, 8
; Line 24
xor eax, eax
pop esi
; Line 26
ret 0
_wmain ENDP
_TEXT ENDS
END
你查看生成的汇编代码?也许你应该在这里发布。 –
用VS2015编译的FYI在调试和释放模式下总是显示'eq eq'。 –
VS调试可能使用FILD或FICOMP,它可以避免int浮点转换(直接与80b浮点寄存器一起工作)。/fp选项也可能会影响行为。 – Suma