2009-04-05 12 views
8

क्या कोई मुझे सी ++ में आकार के ऑपरेटर के कार्यान्वयन और इसके क्रियान्वयन के बारे में कुछ विवरण बता सकता है।आकार का ऑपरेटर सी ++ में कैसे कार्यान्वित किया जाता है?

आकार एक ऑपरेटर है जिसे अधिभारित नहीं किया जा सकता है।

तो इसका मतलब है कि हम इसका डिफ़ॉल्ट व्यवहार नहीं बदल सकते हैं?

+3

क्या संभावित उपयोग आप इस तरह के एक परिदृश्य के लिए हो सकता था? – Mikeage

+2

वाह, ओवरलोडिंग आकार के कारण होने वाली क्षति के बारे में सोचें :-) – paxdiablo

+0

मेरा इरादा सिर्फ आकार के ऑपरेटर के आंतरिक कार्यान्वयन को देखने के लिए है। – anand

उत्तर

22

sizeof सी ++ में वास्तविक ऑपरेटर नहीं है। यह केवल विशेष वाक्यविन्यास है जो तर्क के आकार के बराबर स्थिर होता है। sizeof कोई रनटाइम समर्थन की आवश्यकता नहीं है या नहीं।

संपादित करें: क्या आप जानना चाहते हैं कि कक्षा/संरचना के आकार को परिभाषित करने के तरीके को कैसे परिभाषित किया जाए? इसके लिए नियम ABI का हिस्सा हैं, और संकलक केवल उन्हें लागू करते हैं। असल में नियम

  1. आदिम प्रकारों के लिए आकार और संरेखण परिभाषाएं शामिल हैं;
  2. विभिन्न बिंदुओं की संरचना, आकार और संरेखण;
  3. संरचनाओं में पैकिंग फ़ील्ड के नियम;
  4. आभासी तालिका से संबंधित सामान (अधिक गूढ़) के बारे में नियम।

हालांकि, Abis platform- और अक्सर विक्रेता विशिष्ट, x86 और पर अर्थात हैं (जैसे) IA64 A के आकार नीचे क्योंकि IA64 असंरेखित डेटा का उपयोग की अनुमति नहीं देता अलग होगा।

struct A 
{ 
    char i ; 
    int j ; 
} ; 

assert (sizeof (A) == 5) ; // x86, MSVC#pragma pack(1) 
assert (sizeof (A) == 8) ; // x86, MSVC default 
assert (sizeof (A) == 16) ; // IA64 
+0

तो यह निरंतर मान यानी चर के आकार की गणना कैसे करता है? – anand

+1

एलियन 01, यह चर के आकार की गणना नहीं करता है। sizeof() संकलित किया गया है ("निष्पादित", यदि आप करेंगे) * संकलन समय * पर। कंपाइलर सही मान डालेगा - जो पहले से ही जानता है। उदाहरण के लिए, 32-बिट x86 आर्किटेक्चर पर, यह पता चलेगा कि इनट 32 बिट लंबा हैं, पॉइंटर्स 32 बिट हैं, आदि –

+1

एलियन 01: मैंने * कंपाइलर * गणना संरचना आकारों के बारे में एक संदर्भ जोड़ा। रनटाइम पर, संरचना आकार निश्चित और ज्ञात होते हैं, जैसा कि आप 'int i = 8 लिखते हैं;' वास्तव में कोई नहीं * * रनटाइम पर * 8 की गणना करता है। –

14

http://en.wikipedia.org/wiki/Sizeof

असल में, Bjarne Stroustrup's C++ FAQ उद्धृत करने के लिए:

sizeof अतिभारित नहीं किया जा सकता क्योंकि इस तरह एक सरणी में एक सूचक incrementing के रूप में निर्मित संचालन, परोक्ष उस पर निर्भर करता है। पर विचार करें:

X a[10]; 
X* p = &a[3]; 
X* q = &a[3]; 
p++; // p points to a[4] 
    // thus the integer value of p must be 
    // sizeof(X) larger than the integer value of q 

इस प्रकार, sizeof (एक्स) प्रोग्रामर द्वारा एक नया और अलग अर्थ बुनियादी भाषा के नियमों के उल्लंघन के बिना नहीं दिया जा सकता।

+0

यह कार्यान्वयन विवरण नहीं देता है। सटीक फ़ंक्शन परिभाषा बेहतर विकल्प हो सकती है। – anand

+0

आकार एक फ़ंक्शन नहीं हो सकता है क्योंकि यह दोनों प्रकारों और मानों को स्वीकार करता है: आकार (int) और sizeof ("123") की तुलना करें। –

+0

एंटोन, यह एक टेम्पलेट हो सकता है और एक प्रकार को बहुत अच्छी तरह से स्वीकार कर सकता है –

7

नहीं, आप इसे बदल नहीं सकते हैं। इसके कार्यान्वयन को देखने से आप क्या सीखना चाहते हैं?

sizeof अधिक बुनियादी परिचालनों का उपयोग कर सी ++ में लिखा नहीं जा सकता है। यह एक फ़ंक्शन नहीं है, या लाइब्रेरी हेडर का हिस्सा उदा। printf या malloc। यह कंपाइलर के अंदर है।

संपादित करें: संकलक ही सी या सी ++ में लिखा है, तो आप इस तरह कार्यान्वयन कुछ किया जा रहा है के बारे में सोच सकते हैं:

size_t calculate_sizeof(expression_or_type) 
{ 
    if (is_type(expression_or_type)) 
    { 
     if (is_array_type(expression_or_type)) 
     { 
      return array_size(exprssoin_or_type) * 
      calculate_sizeof(underlying_type_of_array(expression_or_type)); 
     } 
     else 
     { 
      switch (expression_or_type) 
      { 
       case int_type: 
       case unsigned_int_type: 
        return 4; //for example 
       case char_type: 
       case unsigned_char_type: 
       case signed_char_type: 
        return 1; 
       case pointer_type: 
        return 4; //for example 

       //etc., for all the built-in types 
       case class_or_struct_type: 
       { 
        int base_size = compiler_overhead(expression_or_type); 
        for (/*loop over each class member*/) 
        { 
          base_size += calculate_sizeof(class_member) + 
           padding(class_member); 
        } 
        return round_up_to_multiple(base_size, 
           alignment_of_type(expression_or_type)); 
       } 
       case union_type: 
       { 
        int max_size = 0; 
        for (/*loop over each class member*/) 
        { 
          max_size = max(max_size, 
          calculate_sizeof(class_member)); 
        } 
        return round_up_to_multiple(max_size, 
          alignment_of_type(expression_or_type)); 
       } 
      } 
     } 
    } 
    else 
    { 
     return calculate_sizeof(type_of(expression_or_type)); 
    } 
} 

नोट है कि बहुत ज्यादा छद्म कोड है। ऐसी कई चीजें हैं जिनमें मैंने शामिल नहीं किया है, लेकिन यह सामान्य विचार है। संकलक शायद वास्तव में ऐसा नहीं करता है।यह संभवतः sizeof(X) लिखते समय पुन: गणना करने के बजाय, किसी प्रकार के आकार (कक्षा सहित) के आकार की गणना करता है। इसे उदाहरण के लिए भी अनुमति है पॉइंटर्स अलग-अलग आकार होते हैं जो वे इंगित करते हैं।

+0

"इसके कार्यान्वयन को देखने से आप क्या सीखना चाहते हैं?" यह एक वैध उत्तर की तरह नहीं दिखता है। – anand

+0

मुझे पता है कि यह एक चकमा है, लेकिन आप वास्तव में कुछ संबंधित समस्या में रुचि रखते हैं जिसका एक आसान जवाब है ... – Doug

5

आकार संकलन समय पर यह करता है। ऑपरेटर अधिभार केवल कार्य होते हैं, और वे रन टाइम पर जो करते हैं वह करते हैं। इसलिए सी ++ मानक ने इसे अनुमति देने के बावजूद आकार को अधिभारित करना संभव नहीं है।

3

आकार एक संकलन-समय ऑपरेटर है, जिसका अर्थ है कि इसका संकलन समय पर मूल्यांकन किया जाता है।

इसे अधिभारित नहीं किया जा सकता है, क्योंकि इसका पहले से ही सभी उपयोगकर्ता परिभाषित प्रकारों पर अर्थ है - आकार() एक वर्ग वह आकार है जो क्लास परिभाषित करता है ऑब्जेक्ट स्मृति में लेता है, और आकार() एक चर है आकार जो ऑब्जेक्ट वेरिएबल नाम स्मृति में है।

-1

वास्तविकता के लिए Gnu C++ compiler के स्रोत पर नज़र डालें, यह कैसे किया जाता है।

1

जब तक आपको यह देखने की आवश्यकता न हो कि सी ++ - विशिष्ट आकारों की गणना कैसे की जाती है (जैसे वी-टेबल के लिए आवंटन), आप प्लान 9 के सी कंपाइलर को देख सकते हैं। जी ++ से निपटने की कोशिश करने से यह बहुत आसान है।

1

वैरिएबल:

#define getsize_var(x) ((char *)(&(x) + 1) - (char *)&(x)) 

प्रकार:

#define getsize_type(type) ((char*)((type*)(1) + 1) - (char*)((type *)(1))) 
संबंधित मुद्दे