आकार शैली: आकार (प्रकार) या आकार का चर?


22

मैंने sizeofमेमोरी-संबंधित ऑपरेशनों के लिए उपयोग की दो शैलियों को देखा है (जैसे memsetया में malloc):

  • sizeof(type), तथा
  • sizeof variable या sizeof(variable)

आप किसे पसंद करेंगे या आप दो शैलियों के मिश्रण का उपयोग करेंगे, और आप प्रत्येक शैली का उपयोग कब करेंगे? प्रत्येक शैली के पेशेवरों और विपक्ष क्या हैं और जब आप उनका उपयोग करते हैं?

एक उदाहरण के रूप में, मैं निम्नलिखित स्थितियों को देख सकता हूँ जहाँ एक शैली मदद करती है और दूसरी नहीं:

जब आपको सूचक अप्रत्यक्ष रूप से गलत मिलता है:

type *var;
...
memset(var, 0, sizeof var);    /* oops */

जब प्रकार बदलता है:

new_type var;    /* changed from old_type to new_type */
...
memset(&var, 0, sizeof(old_type));    /* oops */

जवाबों:


30

मैं sizeof(variable)खत्म हो गया sizeof(type)। विचार करें:

int a1;
float a2;
memset(&a1,0,sizeof(a1));
memset(&a2,0,sizeof(a2));

बनाम

int a1;
float a2;
memset(&a1,0,sizeof(int));
memset(&a2,0,sizeof(float));

पहले मामले में, यह सत्यापित करना आसान है कि सही आकार पास किए जा रहे हैं memset। दूसरे मामले में, आपको लगातार और नीचे के खंडों की समीक्षा करने की ज़रूरत है ताकि आप सुसंगत हो सकें।


4
इसके अलावा, यदि आप चर के प्रकार को बदलते हैं, तो कोड मान लेता है कि परिवर्तन करना होगा। मुझे लगता है कि यह सही कोड के लिए बेहतर है जितना संभव हो उतना कम निर्भरता। (मैं दिन में 16 बिट से 32 बिट रूपांतरण परियोजना से प्रभावित हूं।)
रोबोट

यह सी सरणियों के साथ काम करने के लिए बेहतर है, जहां टाइपफ़ेड बनाना आम नहीं है, लेकिन चार सरणी जैसी चीजों का उपयोग करें [MAX_SIZE];
मटनज़

@ vy32: गलत 1: "sizeof (सरणी) सरणी का आकार नहीं लौटाता है ... सूचक का आकार सरणी में" - यदि arrayवास्तव में एक C सरणी है, तो sizeof(array)सरणी तत्वों को संग्रहीत करने के लिए आवश्यक बाइट्स की संख्या लौटाता है । यदि arrayएक क्षयित सी सरणी के पहले तत्व के लिए एक संकेतक है, तो आपका कथन है। एक फ़ंक्शन तर्क के रूप में एक सी सरणी पास करना यह फ़ंक्शन में एक सूचक की तरह दिखता है - यह साबित करने वाली सभी जानकारी एक सरणी थी, जैसे कि इसका आकार, खो गया है। इसीलिए इसका क्षय होता हैगलत 2: "सरणियां वास्तव में सी में मौजूद नहीं हैं; ... केवल संकेत के लिए सिंटैक्टिक चीनी।"
जोहान गेरेल

9

वरीयता (हमेशा की तरह) सीधे आपके इरादे को प्रतिबिंबित करना है।

क्या मौजूदा वैरिएबल की मेमोरी के खिलाफ काम करने का इरादा है? यदि ऐसा है, तो उपयोग करें sizeof(variable), क्योंकि यह जितना संभव हो उतना बारीकी से दिखाता है कि यह चर की स्मृति है जिसे आप परवाह करते हैं।

क्या प्रकार पर कुछ गणना करने का इरादा है, उदाहरण के लिए यह निर्धारित करने के लिए कि नए उदाहरण के लिए कितनी मेमोरी आवंटित की जानी चाहिए? यदि ऐसा है, तो उपयोग करें sizeof(type)

यानी, मुझे पसंद है

struct foo *bar;
bar = (struct foo *) malloc(sizeof(struct foo));

ऊपर

bar = (struct foo *) malloc(sizeof(*bar));

जैसा कि बाद का मामला है , ऐसा लगता है कि आप एक चर का उपयोग करने की कोशिश कर रहे हैं जो अभी तक मौजूद नहीं है।

दूसरी ओर, मैं पसंद करता हूं

char Buffer[256];
memset(Buffer, 0, sizeof(Buffer));

ऊपर

char Buffer[256];
memset(Buffer, 0, 256 * sizeof(char));

जैसा कि इरादा स्पष्ट रूप से चर की सामग्री को शून्य-भरना है, इसलिए यह वह चर है जिसके खिलाफ हमें काम करना चाहिए। केवल मेटाडाटा के प्रकार का उपयोग करने की कोशिश करना, चीजों को भ्रमित करता है, यहाँ।



मैं हमेशा करता हूं, लेकिन यह व्यक्तिगत स्वाद की बात है। मुझे लगता है कि void *स्वचालित रूप से अन्य पॉइंटर प्रकारों को एक मिसफिट होने के लिए तैयार किया जाता है।
ऐदन कल्ली

3

मैं बहुत sizeof(type)अधिक पसंद करेंगे sizeof variable। भले ही यह आपको प्रकार के बारे में अधिक चिंता करने और अधिक परिवर्तन करने के लिए मजबूर करता है, यह आपको सूचक अप्रत्यक्ष गलतियों से बचने में मदद करता है, जो सी में बग के सबसे आम कारण में रैंक करते हैं

मैं कीड़े के बारे में इतनी चिंता नहीं करूँगा जहाँ प्रकार sizeof(type)बदल जाता है; जब भी आप एक चर के प्रकार को बदलते हैं, तो आपको यह देखने के लिए एक त्वरित स्कैन करना चाहिए कि उस चर का उपयोग कहां किया गया है और यदि आपको कोई sizeof(type)कथन बदलने की आवश्यकता है । हालांकि यह गलत होने की संभावना हमेशा होती है, लेकिन इसमें सूचक अप्रत्यक्ष गलतियों की तुलना में बहुत कम जोखिम होता है।

इसका एक फ़ायदा sizeof variableसरणियों के लिए है, लेकिन व्यवहार में मैंने पाया है कि पहले / लेन के जोड़े के रूप में पासिंग ऐरे बहुत अधिक सामान्य है (जिस स्थिति में सिर्फ लंबाई का उपयोग होता है), और इसके कारण आकार को गलत करना भी बहुत आसान है सरणी / सूचक क्षय, इस उदाहरण में:

ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) {
  memcpy( mat, src, sizeof( src ) );    /* NOT the same as 3*3*sizeof(float) */
}

2
"त्वरित स्कैन यह देखने के लिए कि उस चर का उपयोग कहां किया गया है .... हमेशा यह गलत होने का एक मौका है" - मेरे लिए यह आकार (प्रकार) करने का सबसे बड़ा खतरा है, यही कारण है कि मैं हमेशा आकार (चर) करता हूं। क्योंकि इस खतरे का अंतिम परिणाम यह है कि सब कुछ अभी भी संकलित हो सकता है और यहां तक ​​कि अगर आप एक गलती करते हैं, तो आपको इसे पकड़ने से पहले एक वर्ष या यादृच्छिक दुर्घटनाओं और बफर भ्रष्टाचार से अधिक समय लग सकता है। और मैं इस सवाल और "सूचक अप्रत्यक्ष गलतियों" के बीच संबंध नहीं बना सका (जाहिर है कि मेरा प्रश्न प्रति समय लगभग 30 सेकंड है)।
DXM

@DXM साइज़ोऑफ़ ऑपरेंड के साथ, यदि यह मान है तो यह sizeof var; अगर यह एक सूचक है sizeof *var। यह भी कुछ ऐसा है जिससे लोग गलत हो सकते हैं, और कंपाइलर खुशी-खुशी इसे बिना किसी शिकायत के ले जाएगा। मैं तर्क देता हूं कि ये गलतियाँ बहुत कठिन हैं, और sizeof(type)फार्म के साथ गलतियों की तुलना में अधिक सामान्य हैं ।
कॉंगसबोंगस

1
आपके दोनों सही - C प्रकार और आकार प्रकार ऑपरेटर मूल रूप से टूटे हुए हैं और कभी भी विश्वसनीय नहीं होंगे, जैसा कि आप प्रोग्रामर इसे ठीक कर सकते हैं कुछ भी नहीं करते हैं।
मटनज

जैसा कि पोस्ट टैग किया गया है C, सी कोड को पोस्ट करना अधिक जानकारीपूर्ण है कि सी ++ कोड पसंद है mat3_t::mat3_t(...)
chux -

0

उद्देश्य अतिरेक को दूर करना है। यदि आप किसी वैरिएबल से संबंधित ऑपरेशन के लिए आकार-प्रकार का उपयोग करते हैं, तो जाहिर है कि आप आकार-प्रकार में प्रतिबिंबित करेंगे। हां, आप पहले उदाहरण की तरह गड़बड़ कर सकते हैं, लेकिन इलाज का उपयोग प्रकार नहीं है, लेकिन * var, सही ढंग से लक्ष्य से मेल खाता है।

इस तरह की समस्याओं को कम करने के लिए मैक्रो, टेम्प्लेट और इसी तरह के औजारों का उपयोग करना होता है जो नग्न आकार के बजाय उपयोग के मामले के लिए प्रशिक्षित होते हैं।

मेरे CLEAR मैक्रो को देखें जो विशेष रूप से नग्न मेमसेट के बजाय उपयोग किया जाता है। अप्रत्यक्ष टाइपो के मामलों में या कई बार जब कोई सामग्री सदिश या स्ट्रिंग उठाती है तो मेरी गांड को बचाती है ...


मैक्रोज़ जैसे कि सी के मैक्रो प्रोग्रामिंग को एक बुरा नाम दिया गया है ......
मैट

@ मट्टनज: कृपया बेहतर विकल्प दिखाएं। यह वास्तव में काम करने वाले कार्यक्रमों की तुलना में सार सामान पर बात करने के लिए आसान है
बालोग पाल

1
लिंक किया गया मैक्रो C ++ है, और इस पोस्ट को 'C' (वे अलग-अलग भाषाएं हैं) टैग किया गया है, Ada मेरा सुझाव होगा।
मटनज़

@mattnz: और एक ही विषय दिखाता है कि सी के लिए समान तरीकों से कैसे लागू किया जाए। आप पूरी तरह से इस बिंदु को याद करते हैं, यह वास्तविक सामग्री कार्यान्वयन नहीं है, बल्कि कच्चे सामान की तुलना में सुरक्षित उपयोग है। Btw तरीके भी पठनीय।
बालग पाल

0

व्यावसायिक तर्क आपकी पसंद को परिभाषित करता है।

  1. यदि आपका कोड किसी विशेष चर को संदर्भित करता है और इस चर के बिना आपके कोड का कोई मतलब नहीं है - चुनें sizeof(var)

  2. यदि आप किसी विशेष प्रकार के चर का एक सेट के साथ सौदा करते हैं - चुनें sizeof(type)। आमतौर पर आपको इसकी आवश्यकता होती है यदि आपके पास एक है typedefजो कई चर को परिभाषित करता है जो आप उनके प्रकार (जैसे क्रमबद्धता) के आधार पर अलग-अलग प्रक्रिया करते हैं। आप नहीं जानते होंगे कि इनमें से कौन सा चर भविष्य के कोड संस्करणों में रहेगा इसलिए तर्क के रूप में चुनना तार्किक रूप से सही है। यहां तक ​​कि इस तरह के बदलने से typedefआपकी आकार रेखा प्रभावित नहीं होगी।


-1

उद्देश्य के आधार पर आकार (चर) सबसे अच्छा समाधान हो सकता है। इस प्रकार, आप अपने चर प्रकार को बदल सकते हैं, यदि आवश्यक हो, तो प्रकार के लिए सभी प्रविष्टियों को ठीक किए बिना। लेकिन फिर, यह आपके उद्देश्य पर निर्भर करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.