gpt4 book ai didi

c++ - Visual Studio 调试与发布版本 : comparing int and float missmatch

转载 作者:可可西里 更新时间:2023-11-01 16:39:19 26 4
gpt4 key购买 nike

看看这个例子:

#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;
}

在 Release模式、gcc 或 g++ (4.9.2) 中使用 Visual Studio 2010 C++ (VS),具有输出

eq
eq

这对我来说是合理的:在第一次比较期间,i 被隐式转换为 float ,其中尾数中的有效位被截断。因此,if 都具有相同的位模式,相当于相等性。在第二个 if 中应用相同的转换,但在定义和初始化 g 时已经执行。

但是,在 Debug模式下使用VS,结果是

neq
eq

看起来,第一个 if 中比较期间的隐式转换(作为 C 和 C++ 中常用算术转换的一部分)没有应用。这是真的?是否有一种 VS 机制可以防止在比较 float 和整数时出现此类误报(更精确地转换为 int/float)?根据MSDN VS C++ 遵循标准。

我已经用 this function 检查了位表示.对于所有编译器,它产生

i = 00000001000000000000000000000001
f = 01001011100000000000000000000000
g = 01001011100000000000000000000000
VS 上的

float.h 声明 #define FLT_MANT_DIG 24 因此所描述的截断问题也应该成立。

我在同一台机器(Intel i5-3570K)上编译了所有内容,但在虚拟框中编译了 VS。在另一台机器上用 VS 编译也会打印 neq/eq

编辑:附加汇编代码

差异_调试.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 ??_C@_04LMPLCMBC@neq?6?$AA@ ; `string'
PUBLIC ??_C@_03HNJPMNDP@eq?6?$AA@ ; `string'
PUBLIC __real@4b800000
PUBLIC _wmain
EXTRN __imp__printf:PROC
EXTRN __fltused:DWORD
EXTRN __RTC_CheckEsp:PROC
EXTRN __RTC_Shutdown:PROC
EXTRN __RTC_InitBase:PROC
; COMDAT ??_C@_04LMPLCMBC@neq?6?$AA@
; File c:\users\user\documents\visual studio 2010\projects\differences\differences\differences.cpp
CONST SEGMENT
??_C@_04LMPLCMBC@neq?6?$AA@ DB 'neq', 0aH, 00H ; `string'
CONST ENDS
; COMDAT ??_C@_03HNJPMNDP@eq?6?$AA@
CONST SEGMENT
??_C@_03HNJPMNDP@eq?6?$AA@ DB 'eq', 0aH, 00H ; `string'
CONST ENDS
; COMDAT __real@4b800000
CONST SEGMENT
__real@4b800000 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 __real@4b800000
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 $LN4@wmain
; Line 14
mov esi, esp
push OFFSET ??_C@_03HNJPMNDP@eq?6?$AA@
call DWORD PTR __imp__printf
add esp, 4
cmp esi, esp
call __RTC_CheckEsp
; Line 15
jmp SHORT $LN3@wmain
$LN4@wmain:
; Line 16
mov esi, esp
push OFFSET ??_C@_04LMPLCMBC@neq?6?$AA@
call DWORD PTR __imp__printf
add esp, 4
cmp esi, esp
call __RTC_CheckEsp
$LN3@wmain:
; Line 19
fld DWORD PTR _g$[ebp]
fld DWORD PTR _f$[ebp]
fucompp
fnstsw ax
test ah, 68 ; 00000044H
jp SHORT $LN2@wmain
; Line 20
mov esi, esp
push OFFSET ??_C@_03HNJPMNDP@eq?6?$AA@
call DWORD PTR __imp__printf
add esp, 4
cmp esi, esp
call __RTC_CheckEsp
; Line 21
jmp SHORT $LN1@wmain
$LN2@wmain:
; Line 22
mov esi, esp
push OFFSET ??_C@_04LMPLCMBC@neq?6?$AA@
call DWORD PTR __imp__printf
add esp, 4
cmp esi, esp
call __RTC_CheckEsp
$LN1@wmain:
; 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 ??_C@_03HNJPMNDP@eq?6?$AA@ ; `string'
PUBLIC ??_C@_04LMPLCMBC@neq?6?$AA@ ; `string'
EXTRN @__security_check_cookie@4:PROC
EXTRN __imp__printf:PROC
; COMDAT ??_C@_04LMPLCMBC@neq?6?$AA@
CONST SEGMENT
??_C@_04LMPLCMBC@neq?6?$AA@ DB 'neq', 0aH, 00H ; `string'
CONST ENDS
; COMDAT ??_C@_03HNJPMNDP@eq?6?$AA@
CONST SEGMENT
??_C@_03HNJPMNDP@eq?6?$AA@ 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 ??_C@_03HNJPMNDP@eq?6?$AA@
call esi
; Line 20
push OFFSET ??_C@_03HNJPMNDP@eq?6?$AA@
call esi
add esp, 8
; Line 24
xor eax, eax
pop esi
; Line 26
ret 0
_wmain ENDP
_TEXT ENDS
END

最佳答案

如果我们分解发布的 ASM:

; Line 14
push OFFSET ??_C@_03HNJPMNDP@eq?6?$AA@
call DWORD PTR __imp__printf
add esp, 4
; Line 18
xor eax, eax
; Line 20
ret 0

它只是打印 eq 并退出,这表明 float 比较刚刚被完全优化掉。对于调试程序集,我们看到它使用 fldfild 指令:

; Line 9
fld DWORD PTR __real@4b800000
fstp DWORD PTR _f$[ebp]
; Line 10
fild DWORD PTR _i$[ebp]
fstp DWORD PTR _g$[ebp]
; Line 13
fild DWORD PTR _i$[ebp]

这些是 IA32 指令,这是 Visual Studio 2010 中使用的默认架构。我怀疑您使用 /arch:SSE2 而不是您会得到不同的结果。

Hans Passant's comment基本上证实了我刚才所说的。

关于c++ - Visual Studio 调试与发布版本 : comparing int and float missmatch,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37162422/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com