जैसा कि अन्य ने पहले से ही नोट किया है, एक गैर-चार प्रकार के पॉइंटर को एक पॉइंटर को एक अलग गैर-चार प्रकार के लिए कास्टिंग करना और फिर डिफ्रेंसिंग अपरिभाषित व्यवहार है।
printf("%08lx\n", *(unsigned long *)&fValue)
अपरिभाषित व्यवहार जरूरी नहीं कि एक प्रोग्राम है जो इस तरह के एक भड़ौआ प्रदर्शन करने के लिए प्रयास करता चल हार्ड ड्राइव विलोपन में परिणाम या नाक राक्षसों (अपरिभाषित व्यवहार के दो पहचान) लोगों को नाक से फूटना कर देगा का आह्वान करते हैं। किसी कंप्यूटर पर जो sizeof(unsigned long)==sizeof(float)
और जिस पर दोनों प्रकार के एक ही संरेखण आवश्यकताओं है में, कि printf
लगभग निश्चित रूप से एक यह जो सवाल में चल बिन्दु मूल्य की हेक्स प्रतिनिधित्व मुद्रित करने के लिए है करने के लिए, उम्मीद है कि क्या करना होगा।
यह आश्चर्यजनक नहीं होना चाहिए। सी मानक खुले तौर पर भाषा का विस्तार करने के लिए कार्यान्वयन आमंत्रित करता है। इनमें से कई एक्सटेंशन उन क्षेत्रों में हैं जो कड़ाई से बोलते हुए, अपरिभाषित व्यवहार हैं। उदाहरण के लिए, POSIX समारोह dlsym एक void*
दिखाए, लेकिन यह फ़ंक्शन आमतौर पर एक वैश्विक चर एक समारोह के बजाय का पता लगाने के लिए प्रयोग किया जाता है। इसका मतलब है कि dlsym
द्वारा लौटाए गए शून्य सूचक को फ़ंक्शन पॉइंटर पर डाला जाना चाहिए और फिर फ़ंक्शन को कॉल करने के लिए संदर्भित किया जाना चाहिए। यह स्पष्ट रूप से अपरिभाषित व्यवहार है, लेकिन फिर भी यह किसी भी POSIX अनुपालन मंच पर काम करता है। यह हार्वर्ड आर्किटेक्चर मशीन पर काम नहीं करेगा जिस पर पॉइंटर्स के कार्यों के डेटा के पॉइंटर्स की तुलना में अलग-अलग आकार होते हैं।
इसी तरह, एक अहस्ताक्षरित पूर्णांक के लिए सूचक के लिए एक float
के सूचक के कास्टिंग और फिर अपसंदर्भन लगभग किसी भी संकलक के साथ लगभग किसी भी कंप्यूटर पर काम करने के लिए होता है, जिसमें कि अहस्ताक्षरित पूर्णांक के आकार और संरेखण आवश्यकताओं की तरह ही हैं एक float
।
ने कहा कि unsigned long
का उपयोग करके आपको परेशानी हो सकती है। मेरे कंप्यूटर पर, unsigned long
64 बिट लंबा है और इसमें 64 बिट संरेखण आवश्यकताएं हैं। यह एक फ्लोट के साथ संगत नहीं है। uint32_t
का उपयोग करना बेहतर होगा - मेरे कंप्यूटर पर, वह है।
typedef struct {
float fval;
uint32_t ival;
} float_uint32_t;
एक float_uint32_t.fval
को नियत और से एक्सेस करते समय एक `` अपरिभाषित व्यवहार हुआ करता था float_uint32_t.ival`:
संघ हैक इस गंदगी के आसपास एक तरीका है। यह अब सी में कोई मामला नहीं है। कोई संकलक जिसे मैं यूनियन हैक के लिए नाक राक्षसों को मारने के बारे में जानता हूं। यह सी ++ में यूबी नहीं था। यह अवैध था। सी ++ 11 तक, एक अनुपालन सी ++ संकलक को शिकायत करने के लिए शिकायत करना पड़ा।
इस गंदगी के आसपास किसी भी और भी बेहतर तरीका %a
प्रारूप है, जो 1999 के बाद से सी मानक का हिस्सा रहा है उपयोग करने के लिए है:
printf ("%a\n", fValue);
यह सरल, आसान, पोर्टेबल है, और कोई अपरिभाषित व्यवहार का मौका। यह प्रश्न में डबल परिशुद्धता फ्लोटिंग पॉइंट मान के हेक्साडेसिमल/द्विआधारी प्रतिनिधित्व को प्रिंट करता है। चूंकि printf
एक पुरातन कार्य है, सभी float
तर्क पर कॉल से पहले double
में परिवर्तित हो गए हैं। यह रूपांतरण सी मानक के 1 999 संस्करण के अनुसार सटीक होना चाहिए। कोई भी scanf
या उसकी बहनों को कॉल के माध्यम से उस सटीक मूल्य को चुन सकता है।
यह अपरिभाषित व्यवहार है। ऐसा कुछ ऐसा है जो 1 9 8 9 में सी को मानकीकृत करने से पहले किया गया था, और कुछ ने –