2011-11-12 12 views
6

का प्रतिनिधित्व करने के लिए आज मेरे पास एक अजीब सवाल है।सी ++ संघ डेटा मेमोरी बनाम सी स्केलर वैरिएबल प्रकार

कोड (सी ++)

#include <iostream> 

union name 
{ 
    int num; 
    float num2; 

}oblong; 


int main(void) 
{ 
    oblong.num2 = 27.881; 

    std::cout << oblong.num << std::endl; 

    return 0; 
} 

कोड (सी)

#include <stdio.h> 

int main(void) 
{ 
    float num = 27.881; 

    printf("%d\n" , num); 

    return 0; 
} 

प्रश्न

  1. जैसा कि हम जानते हैं, सी ++ यूनियनों कर सकते हैं होल एक से अधिक प्रकार के डेटा तत्व लेकिन एक समय में केवल एक ही प्रकार। तो मूल रूप से name oblong केवल स्मृति का एक हिस्सा आरक्षित करेगा जो 32-बिट है (क्योंकि संघ में सबसे बड़ा प्रकार 32-बिट, int और float है) और यह भाग या तो एक पूर्णांक या फ्लोट रख सकता है।

  2. तो मैं केवल 27.881 का मान oblong.num2 (जैसा कि आप उपरोक्त कोड पर देख सकते हैं) असाइन करते हैं। लेकिन जिज्ञासा से, मैं oblong.num का उपयोग कर स्मृति का उपयोग करता हूं जो एक ही स्मृति स्थान को इंगित कर रहा है।

  3. जैसी उम्मीद थी, यह मुझे एक मूल्य के जो 27 नहीं है क्योंकि जिस तरह से नाव और पूर्णांक एक स्मृति के अंदर का प्रतिनिधित्व अलग है दे दी है, यही कारण है कि जब मैं oblong.num का उपयोग स्मृति भाग एक्सेस करने के लिए स्मृति मूल्य के उस भाग का इलाज करेंगे पूर्णांक के रूप में पूर्णांक के रूप में पूर्णांक और व्याख्या के रूप में।

  4. मैं जानता हूँ कि यह घटना भी सी में क्या होगा, यही कारण है कि मैं एक मूल्य के साथ एक नाव प्रकार चर को प्रारंभ किया और बाद में %d तो का उपयोग कर इसे पढ़ा है मैं तो बस यह एक ही मूल्य 27.881 का उपयोग करके बाहर की कोशिश है जो आप कर सकते हैं ऊपर देखो। लेकिन जब मैं इसे चलाता हूं, तो कुछ अजीब होता है, जो कि सी में मिलता है उसका मूल्य सी ++ से अलग होता है।

  5. ऐसा क्यों होता है? मुझे पता है कि अंत में दो कोडों से प्राप्त होने वाले दो मूल्य कचरे के मूल्य नहीं हैं, लेकिन मुझे अलग-अलग मूल्य क्यों मिलते हैं? मैं सी और सी ++ पूर्णांक और फ्लोट आकार दोनों को सत्यापित करने के आकार का भी उपयोग करता हूं और दोनों 32-बिट हैं। तो स्मृति आकार ऐसा नहीं होता है जो ऐसा होता है, तो मूल्यों में यह अंतर क्या होता है?

+1

वही मामला: http://stackoverflow.com/questions/2377733/how-does-this-program-work और यह भी: http://stackoverflow.com/questions/2398791/how-is-conversion- ऑफ-फ्लोट-डबल-टू-इंट-हैंडल-इन-प्रिंटफ –

+0

अंतर सी बनाम सी ++ नहीं है। आप सी ++ में भी दूसरा उदाहरण संकलित कर सकते हैं, और सी और सी ++ से एक ही परिणाम प्राप्त कर सकते हैं। 'संघ' के साथ पहला उदाहरण 'std :: cout <<' के बजाय 'printf' का उपयोग करने के लिए एक छोटे से परिवर्तन की आवश्यकता होगी, लेकिन इसके बाद आपको सी और सी ++ से वही परिणाम मिलेंगे। – MSalters

उत्तर

9

सबसे पहले, गलत printf() प्रारूप स्ट्रिंग होने अपरिभाषित व्यवहार है। अब जब कि, ने कहा कि यहाँ है क्या वास्तव में अपने मामले में हो रहा है:

ऐसे printf() रूप vararg काम करता है, पूर्णांकों int की तुलना में छोटे में int के लिए प्रोत्साहित किया और तैरता double की तुलना में छोटे double करने के लिए प्रोत्साहित कर रहे हैं।

परिणाम यह है कि आपके 27.881 को 8-बाइट डबल में परिवर्तित किया जा रहा है क्योंकि इसे printf() में पारित किया गया है। इसलिए, द्विआधारी प्रतिनिधित्व अब float जैसा नहीं है।

प्रारूप स्ट्रिंग %d एक 4-बाइट पूर्णांक की अपेक्षा करता है। तो असल में, आप 27.881 के डबल-परिशुद्धता प्रतिनिधित्व के निचले 4-बाइट प्रिंट करेंगे।(थोड़ा-endian कल्पना करते हुए)

* वास्तव में (सख्त-FP कल्पना करते हुए), आप 27.881 के नीचे 4-बाइट देख रहे हैं के बाद यह float लिए डाली है, और फिर double के लिए प्रोत्साहित किया।

2

दोनों मामलों में आप अपरिभाषित व्यवहार का सामना कर रहे हैं। आपका कार्यान्वयन बस कुछ अजीब करने के लिए होता है।

+0

दोनों मामले? मैंने सोचा कि केवल दूसरा प्रिंटफ अपरिभाषित है। पहला फ्लोट से आने वाले एक अच्छी तरह से परिभाषित बिटपटर के साथ एक डंप है। (इसके लिए यह समझ में आता है कि पाठ्यक्रम का एक और सवाल है) – Bort

+0

पहला मामला यूबी है क्योंकि आप ऑब्जेक्ट 'फ्लोट (27.881)' ऑब्जेक्ट को 'int'' की अभिव्यक्ति के माध्यम से एक्सेस कर रहे हैं। ऑब्जेक्ट्स को या तो अपने स्वयं के प्रकार की अभिव्यक्ति के माध्यम से या (हस्ताक्षरित) 'char []' के माध्यम से एक्सेस किया जाना चाहिए। उत्तरार्द्ध नियम है ताकि आप ऑब्जेक्ट्स को 'memcpy' कर सकें (सी में; सी ++ पुराने डेटा को सादा करने के लिए 'memcpy' प्रतिबंधित करता है)। – MSalters

संबंधित मुद्दे