2016-02-07 14 views
7

मैं सी भाषा में नया हूं और केवल structs और पॉइंटर्स के बारे में सीखा।ऑफ़सेट मैक्रो आवश्यक क्यों है?

मेरा प्रश्न हाल ही में देखा गया offsetof मैक्रो से संबंधित है। मुझे पता है कि यह कैसे काम करता है और इसके पीछे तर्क।

<stddef.h> फ़ाइल में इस प्रकार परिभाषा है:

#define offsetof(type,member) ((unsigned long) &(((type*)0)->member)) 

मेरे सवाल है, अगर मैं एक struct के रूप में नीचे देख सकते हैं:

struct test { 
    int field1: 
    int field2: 
}; 

struct test var; 

क्यों नहीं मैं सीधे field2 का पता प्राप्त कर सकते हैं के रूप में:

char * p = (char *)&var; 
char *addressofField2 = p + sizeof(int); 

कुछ लिखने की बजाय यह

field2Offset = offsetof (struct test, field2); 

और फिर var के प्रारंभिक पते पर ऑफसेट मान जोड़ना?

क्या कोई अंतर है? offsetof अधिक कुशल का उपयोग कर रहा है?

+0

यदि आप सी के लिए नए हैं, तो 'ऑफ़सेट' और हाथों से हाथ हटाएं। आपको सामान्य प्रोग्रामिंग के लिए इसकी आवश्यकता नहीं होगी, लेकिन शुरुआत में केवल उन्नत सुविधाएं ही गड़बड़ी की संभावना होगी। - अपराध नहीं, लेकिन एक बहुत अच्छी तरह से चेतावनी चेतावनी! – Olaf

उत्तर

4

सी संकलक अक्सर दक्षता में सुधार और पूर्णांकों शब्द गठबंधन (जो कुछ आर्किटेक्चर में bus errors और कुछ आर्किटेक्चर में से बचने के लिए आवश्यक है दक्षता से बचने के लिए आवश्यक है रखने के क्रम में एक struct के सदस्यों के बीच अतिरिक्त गद्दी बिट्स या बाइट्स जोड़ देगा समस्या का)।

struct ImLikelyPadded { 
    int x; 
    char y; 
    int z; 
}; 

आपको पता चल सकता है कि sizeof(struct ImLikelyPadded) 12, नहीं 9 है, क्योंकि संकलक एक-बाइट char y के अंत और के बीच तीन अतिरिक्त पैडिंग बाइट्स से जोड़ दिया जाएगा: उदाहरण के लिए, कई compilers में, अगर आप इस struct है शब्द-आकार int z। यही कारण है कि offsetof इतना उपयोगी है - यह आपको यह निर्धारित करने देता है कि चीजें वास्तव में पैडिंग बाइट्स में फैक्टरिंग कर रही हैं और अत्यधिक पोर्टेबल है।

+1

एक अतिरिक्त के रूप में, मैक्रो में यूबी के साथ कार्यान्वयन का एकमात्र कारण यह है कि यह * कार्यान्वयन है। – Deduplicator

0

सरणी के विपरीत, संरचना का मेमोरी लेआउट हमेशा संगत नहीं होता है। मेमोरी को संरेखित करने के लिए कंपाइलर अतिरिक्त बाइट जोड़ सकता है। इसे padding कहा जाता है।

पैडिंग के कारण, हमें मैन्युअल रूप से सदस्य का स्थान ढूंढना मुश्किल होता है। यही कारण है कि हम हमेशा संरचना आकार खोजने के लिए आकार का उपयोग करते हैं।

ऑफ़सेट, मैक्रो आपको संरचना की स्ट्रेटिंग स्थिति से संरचना के सदस्य की दूरी, ऑफसेट, पता लगाने देता है।

लिनक्स कर्नेल के container_of मैक्रो में ऑफ़सेटफ़ोन को देखा जाने वाला एक बुद्धिमान उपयोग। यह मैक्रो आपको जेनेरिक समावेशी दोगुनी लिंक्ड सूची

0

में सदस्य के पते को देखते हुए नोड की प्रारंभिक स्थिति खोजने देता है जैसा कि पहले से ही अन्य उत्तरों में उल्लिखित है, पैडिंग कारणों में से एक है। मैं इसके बारे में पहले से क्या कहा था दोहराना नहीं होगा।

offsetof मैक्रो का उपयोग करने का एक और अच्छा कारण है और मैन्युअल रूप से ऑफसेट्स की गणना नहीं करना है कि आपको केवल इसे एक बार लिखना है। कल्पना करें कि क्या होता है यदि आपको field1 के प्रकार को बदलने की आवश्यकता है या field2 के सामने एक या अधिक फ़ील्ड डालें या हटा दें। अपनी हाथ से तैयार गणना का उपयोग करके आपको अपनी सभी घटनाओं को ढूंढना और बदलना होगा। उनमें से एक गायब रहस्यमय बग का उत्पादन करेगा जो खोजने में मुश्किल है।

offsetof का उपयोग करके लिखे गए कोड को इस स्थिति में किसी भी अपडेट की आवश्यकता नहीं है। संकलक अगले संकलन पर सब कुछ का ख्याल रखता है।

और भी, offsetof का उपयोग करने वाला कोड अधिक स्पष्ट है। मैक्रो मानक है, इसकी कार्यक्षमता documented है। एक साथी प्रोग्रामर जो कोड पढ़ता है उसे तुरंत समझता है। हाथ से तैयार किए गए कोड प्रयासों को समझना इतना आसान नहीं है।

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