सबसे पहले, जैसा कि कई अन्य उत्तरों में स्पर्श किया गया है, लेकिन मेरे दिमाग में नहीं, स्पष्ट रूप से पर्याप्त रूप से लिखा गया है: यह अधिकांश संदर्भों में एक पूर्णांक प्रदान करने के लिए काम करता है जहां एक लाइब्रेरी फ़ंक्शन या तर्क लेता है । संकलक स्वचालित रूप से एक रूपांतरण सम्मिलित करेगा। उदाहरण के लिए, अच्छी तरह से परिभाषित है और बिल्कुल वैसा ही व्यवहार करेगा , और वहां उपयोग किए गए किसी भी अन्य पूर्णांक-प्रकार की अभिव्यक्ति के लिए भी यही सच है।doublefloatsqrt(0)sqrt((double)0)
printfफरक है। यह भिन्न है क्योंकि यह तर्कों की एक चर संख्या लेता है। इसका फंक्शन प्रोटोटाइप है
extern int printf(const char *fmt, ...);
इसलिए, जब आप लिखते हैं
printf(message, 0)
कंपाइलर को इस बारे में कोई जानकारी नहीं है कि किस प्रकार के दूसरे तर्क की printf अपेक्षा है। इसमें केवल तर्क अभिव्यक्ति का प्रकार है, जो हैint द्वारा जाना है। इसलिए, अधिकांश पुस्तकालय कार्यों के विपरीत, यह आप पर है, प्रोग्रामर, यह सुनिश्चित करने के लिए कि तर्क सूची प्रारूप स्ट्रिंग की अपेक्षाओं से मेल खाती है।
(आधुनिक संकलक एक प्रारूप स्ट्रिंग में देख सकते हैं और आपको बता सकते हैं कि आपको एक प्रकार का बेमेल मिल गया है, लेकिन वे आपका क्या मतलब है इसे पूरा करने के लिए रूपांतरण डालना शुरू नहीं करने जा रहे हैं, क्योंकि बेहतर होगा कि आपका कोड अब टूट जाए, जब आप देखेंगे , वर्षों बाद जब एक कम सहायक संकलक के साथ पुनर्निर्माण किया गया।)
अब, सवाल का दूसरा आधा हिस्सा था: यह देखते हुए कि (int) 0 और (फ्लोट) 0.0 सबसे आधुनिक प्रणालियों पर हैं, दोनों को 32 बिट्स के रूप में दर्शाया गया है, जो सभी शून्य हैं, वैसे भी यह दुर्घटना से काम क्यों नहीं करता है? सी मानक केवल यह कहता है "यह काम करने के लिए आवश्यक नहीं है, आप अपने दम पर हैं", लेकिन मुझे दो सबसे सामान्य कारणों के बारे में बताएं कि यह काम क्यों नहीं करेगा; यह शायद आपको यह समझने में मदद करेगा कि क्यों यह आवश्यकता नहीं है।
सबसे पहले, ऐतिहासिक कारणों से, जब आप floatएक चर तर्क सूची से गुजरते हैं, तो इसका प्रचार हो जाता है double, जो कि अधिकांश आधुनिक प्रणालियों पर, 64 बिट्स चौड़ा होता है। तो printf("%f", 0)उनमें से 64 को उम्मीद है कि केवल 32 शून्य बिट्स एक कैली को पास करता है।
दूसरा, समान रूप से महत्वपूर्ण कारण यह है कि फ्लोटिंग-पॉइंट फ़ंक्शन तर्क पूर्णांक तर्कों की तुलना में एक अलग स्थान पर पारित किए जा सकते हैं । उदाहरण के लिए, अधिकांश सीपीयू में पूर्णांक और फ्लोटिंग-पॉइंट मानों के लिए अलग-अलग रजिस्टर फाइलें होती हैं, इसलिए यह एक नियम हो सकता है कि तर्क 4 में से 4 r4 के माध्यम से रजिस्टरों r0 में जाते हैं यदि वे पूर्णांक हैं, लेकिन f0 के माध्यम से f0 अगर वे फ्लोटिंग-पॉइंट हैं। तो printf("%f", 0)उस शून्य के लिए रजिस्टर एफ 1 में दिखता है, लेकिन यह बिल्कुल भी नहीं है।
printfउम्मीद कर रहा हैdoubleऔर आप इसे दे रहे हैं aint।floatऔरintआपकी मशीन पर समान आकार हो सकता है, लेकिन0.0fवास्तव मेंdoubleजब इसे एक वैरिएड तर्क सूची में धकेल दिया जाता है (औरprintfउम्मीद करता है)। संक्षेप में, आपprintfअपने उपयोग और आपके द्वारा प्रदान किए गए तर्कों के आधार पर सौदेबाजी के अपने अंत को पूरा नहीं कर रहे हैं।