9

इस उदाहरण पर एक नज़र डालें:दृश्य स्टूडियो डिबग बनाम रिहाई का निर्माण: पूर्णांक की तुलना और नाव 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; 
} 

जो, विजुअल स्टूडियो 2010 सी ++ (वी.एस.) को रिलीज़ मोड, जीसीसी, या जी ++ में उपयोग करते हुए (4.9 .2), उत्पादन

eq 
eq 

जो मेरे लिए उचित है है: पहली तुलना के दौरान, i परोक्ष एक नाव जहां अपूर्णांश में महत्वपूर्ण बिट छोटा किया गया है में बदल जाती है। इस प्रकार, i और f दोनों समान पैटर्न हैं जो समानता की तुलना करते हैं। दूसरे if में वही रूपांतरण लागू होता है लेकिन g को परिभाषित और प्रारंभ करते समय पहले से ही किया गया था।

हालांकि, डिबग मोड में वी.एस. उपयोग करते हुए, परिणाम

neq 
eq 

ऐसा लगता है, पहली if में तुलना (सी और सी में सामान्य गणित रूपांतरण ++ के हिस्से के रूप) के दौरान अंतर्निहित रूपांतरण लागू नहीं किया जाता है । क्या ये सच है? क्या कोई वीएस-तंत्र है जो फ्लोट्स और इनट्स (इंट/फ्लोट में अधिक सटीकता के साथ रूपांतरण) की तुलना में ऐसे झूठे सकारात्मक रोकता है? MSDN वीएस सी ++ के अनुसार मानक का पालन करता है।

मैंने this function के साथ थोड़ा सा प्रतिनिधित्व देखा है। सभी compilers के लिए यह

i = 00000001000000000000000000000001 
f = 01001011100000000000000000000000 
g = 01001011100000000000000000000000 

float.h वी.एस. पर करने के लिए कहा गया है पैदावार #define FLT_MANT_DIG 24 तो वर्णित काट-छांट मुद्दे के रूप में अच्छी तरह से धारण करना चाहिए।

मैंने सभी एक ही मशीन (इंटेल i5-3570K) पर संकलित किया लेकिन वर्चुअल बॉक्स में वीएस के लिए। किसी अन्य मशीन पर वीएस के साथ संकलन 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 
+3

आप उत्पन्न कोडांतरक कोड को देखो क्या इस्तेमाल कर सकते हैं बाध्य करने के लिए? शायद आपको इसे यहां पोस्ट करना चाहिए। –

+0

वीवाई2015 के साथ संकलित एफवाईआई यह डीबग और रिलीज मोड में हमेशा 'eq eq' प्रदर्शित करता है। –

+0

वीएस डीबग FILD या FICOMP का उपयोग कर सकता है, जो अंतर को फ़्लोट करने के लिए int से बचाता है (सीधे 80 बी फ्लोट रजिस्टरों के साथ काम करता है)।/एफपी विकल्प व्यवहार को भी प्रभावित कर सकता है। – Suma

उत्तर

6

हम रिहाई एएसएम demangle हैं:

; Line 14 
    push OFFSET [email protected][email protected][email protected] 
    call DWORD PTR __imp__printf 
    add esp, 4 
; Line 18 
    xor eax, eax 
; Line 20 
    ret 0 

यह सिर्फ eq प्रिंट कर रहा है और बाहर निकल रहा है, जो बताता है कि फ़्लोटिंग तुलना पूरी तरह से अनुकूलित है। डिबग विधानसभा के लिए, हम यह fld और fild निर्देशों का उपयोग कर देखें:

; 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] 

ये IA32 निर्देश जो कि डिफ़ॉल्ट मुझे लगता है दृश्य स्टूडियो 2010 में इस्तेमाल किया वास्तुकला है कि आप /arch:SSE2 का उपयोग करने के बजाय आप अलग अलग परिणाम प्राप्त करेंगे।

Hans Passant's comment अनिवार्य रूप से पुष्टि करता है कि मैंने अभी क्या कहा है।

+2

का उपयोग करके अक्षम करना संभव होना चाहिए हां, जोड़ना/arch: संकलन विकल्पों में एसएसई 2 डीबग मोड में 'eq/eq' प्रिंट करता है। User6320439 और हंसपैसेंट के स्पष्टीकरण के लिए धन्यवाद – johannes

0

आउटपुट के दोनों सेट अनुपालन सी व्यवहार हैं।

एफपी गणित करने में, सी ऑपरेटरों के प्रारूप की तुलना में एफपी गणना उच्च परिशुद्धता स्तर पर होने की अनुमति देता है।

यदि कोड i == fdouble गणित के रूप में करता है, तो परिणाम "neq" है।
यदि कोड i == ffloat गणित के रूप में करता है, तो परिणाम "eq" है।

int i= 16777217; 
float f = 16777216.0; 
if(i == f) 
    printf("eq\n"); 
else 
    printf("neq\n"); 

काम और कलाकारों (जो सभी अतिरिक्त सीमा और परिशुद्धता निकालने के लिए) को छोड़कर चल ऑपरेंड साथ ऑपरेटरों द्वारा उत्पन्न होने वाले मूल्यों और सामान्य गणित रूपांतरण करने के लिए और अस्थायी स्थिरांक की करने के लिए मूल्यांकन किया जाता है विषय को महत्व देता है एक प्रारूप जिसका रेंज और सटीक अधिक हो सकता है की तुलना में प्रकार C11 §5.2.4.2.2 9

आधुनिक सी compilers FLT_EVAL_METHOD प्रदान जो इंगित करता है कि क्या प्रयोग किया जाता है के लिए आवश्यक।


वहाँ एक वी.एस.-व्यवस्था है जिसके तैरता और ints (रूपांतरण अधिक परिशुद्धता के साथ/नाव int करने के लिए) की तुलना में इस तरह के झूठे सकारात्मक रोकता है?

एक float तुलना, कोड

if((float) i == f) 

बाध्य करने के लिए इस्तेमाल कर सकते हैं एक double तुलना, कोड

if((double) i == f) 
संबंधित मुद्दे