2008-12-17 11 views
20

हाल ही में किसी ने किसी अन्य उपयोगकर्ता को आकार (प्रकार) के बजाय आकार के var के उपयोग पर किसी अन्य उपयोगकर्ता की सराहना करते हुए देखा। मैंने हमेशा सोचा था कि सिर्फ एक शैली पसंद था। क्या कोई महत्वपूर्ण अंतर है? उदाहरण के लिए, च और एफएफ के साथ लाइनों ग्राम और gg के साथ लाइनों की तुलना में बेहतर माना गया:"सी" आकार किसी प्रकार या चर के साथ

typedef struct _foo {} foo; 

foo *f = malloc(count * sizeof f); 
foo *g = malloc(sizeof(foo) * count); 

foo **ff = malloc(count * sizeof *ff); 
foo **gg = malloc(sizeof(foo*) * count); 

मेरी राय में, पहला सेट शैली का सिर्फ एक मामला है। लेकिन लाइनों की दूसरी जोड़ी में, अतिरिक्त दूसरा * आसानी से गुणा के लिए भ्रमित हो सकता है।

+3

आपके पास अपनी पहली 'मॉलोक' लाइन में एक बग है - यह 'sizeof * f' होना चाहिए। सामान्य पैटर्न 'somevar = malloc (गिनती * आकार * somevar) 'है। – caf

उत्तर

45

यदि चर का प्रकार बदल दिया गया है, तो आकार को बदलने के बजाय आकार को बदलने की आवश्यकता नहीं होगी।

@ आईपैप की टिप्पणी के संबंध में: प्रकार बनाम परिवर्तनीय नाम के लिए परिवर्तन की संभावना या संभावना समस्या नहीं है। कल्पना करें कि परिवर्तनीय नाम का आकार आकार के तर्क के रूप में उपयोग किया जाता है और फिर बाद में बदला जाता है। सबसे अच्छे मामले में एक रिफैक्टर-नामकरण ऑपरेशन सभी घटनाओं को बदलता है और कोई त्रुटि नहीं पेश की जाती है। सबसे बुरे मामले में एक आकार का एक उदाहरण याद किया जाता है और संकलक शिकायत करता है और आप इसे ठीक करते हैं। यदि प्रकार बदल गया है तो आप कर रहे हैं, आकार के बयान में त्रुटियों की कोई संभावना नहीं है।

अब कल्पना करें कि आकार आकार के लिए तर्क है। यदि चर का प्रकार बदल दिया गया है, तो उस चर से संबंधित सभी आकारों को खोजने के निरीक्षण के अलावा अन्य साधन नहीं हैं। आप खोज सकते हैं, लेकिन आपको उसी प्रकार के आकार के सभी असंबंधित उपयोगों के लिए हिट मिलेगी। यदि कोई चूक गया है, तो आपके पास आकार मिलान के कारण रनटाइम समस्या होगी, जो खोजने में बहुत अधिक परेशानी है।

+1

सरणी चर के लिए, आकार (सरणी) आपको सरणी का असली आकार देगा। इसका उपयोग आकार (सरणी)/sizeof (तत्व) के तत्वों की संख्या की गणना करने के लिए किया जा सकता है। ध्यान दें कि यह एक सूचक के माध्यम से द्विपक्षीय आवंटित स्मृति के लिए काम नहीं करेगा। –

+2

एक व्यावहारिक तर्क नहीं है। वैसे ही यह दावा करना संभव है कि यदि चर का नाम बदल दिया गया है, तो आकार बदलने के बजाय आकार को तर्क की आवश्यकता नहीं होगी। या तो परिवर्तन की संभावना विशिष्ट डिजाइन पर निर्भर करती है (और ज्यादातर मामलों में न तो बदलना चाहिए या बदलना चाहिए) – SomeWittyUsername

+0

यह उत्तर एक "अंतिम" समाधान प्रतीत नहीं होता है, यह ध्यान में रखते हुए कि यह मामलों को कवर नहीं करता है जब कोड तर्क टाइपिफ़ पर निर्भर करता है एक विशेष चर पर। आप नीचे मेरा जवाब देख सकते हैं। – Riga

3

लाइनें एफ और एफएफ निश्चित रूप से जी और जीजी से भी बदतर हैं। sizeof f सूचक आकार है, क्योंकि एफ एक बिंदु है। उन्हें समकक्ष बनाने के लिए, आपको sizeof *f लिखना होगा (या, बेहतर सुगमता के लिए, sizeof(*f))।

6

स्टीव के कहने के अलावा, मुझे वह आकार जोड़ने दें जो इसके ऑपरेंड का मूल्यांकन नहीं करता है। तो आप इसमें कुछ भी करने के लिए स्वतंत्र हैं। न केवल आप अभी तक प्रारंभिक चर का उपयोग कर सकते हैं, लेकिन आप एक नल-पॉइंटर को अस्वीकार कर सकते हैं, कॉल फ़ंक्शंस परिभाषित नहीं किए गए हैं, बल्कि केवल घोषित किए गए हैं और किसी अन्य प्रकार की सामग्री भी करते हैं। स्टीव ने काफी समझाया है कि मैं हमेशा अभिव्यक्ति संस्करण का उपयोग करने के लिए प्रोत्साहित करता हूं।

यह भी मान लें कि कभी-कभी टाइपनाम वास्तव में लंबे और अपठनीय होते हैं, केवल पॉइंटर्स को फ़ंक्शन (विशेष रूप से सी ++ में) के बारे में सोचें। sizeof(my_long_type<weird, stuff>) लिखने के बजाय आप बस sizeof t करें।

+0

4 साल बीत चुके हैं और सी ++ में लंबे प्रकार के नाम की समस्या 'decltype' के साथ कम हो गई है :) – SomeWittyUsername

0

एक चर के आकार को लेना अप्रत्याशित परिणाम हो सकता है। जब चर एक सरणी है, आकार (सरणी) सरणी के आकार को वापस कर देगा, न कि किसी व्यक्तिगत तत्व का आकार या सूचक का आकार। एक सूचक का आकार लेना एक सूचक के आकार को वापस कर देगा। लेकिन जब से चारों ओर पारित होने पर सरणी को आमतौर पर पॉइंटर्स के रूप में दर्शाया जाता है, तो चीजें भ्रमित हो सकती हैं।

+1

जबकि पहली पंक्ति भ्रामक है: परिणाम में अप्रत्याशित कुछ भी नहीं है, दूसरा वाक्य अन्य सभी उत्तरों से गायब है: sizeof (array) आपको पूरे सरणी का आकार देगा, न कि तत्व। इसका उपयोग आकार (सरणी)/आकार (तत्व) –

+0

@dribeas के तत्वों की गणना करने के लिए किया जा सकता है: हां, इसलिए '# डीआईएम (x) परिभाषित करें (आकार (x)/sizeof (* (x)))' के लिए संभावित मैक्रो नामों की विविधता (ARRAY_SIZE, DIMENSION, ...)। –

2

मैं स्मृति आवंटन में sizeof(type) का उपयोग करता हूं, लेकिन स्थानीय या वैश्विक चर का उपयोग करते समय हमेशा sizeof(variable) का उपयोग करता हूं। फिर भी, हर समय परिवर्तनीय नाम का उपयोग करने के लिए सलाह में ज्ञान है।

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

एक बिलकुल अलग कील पर, sizeof के बारे में अन्य बिंदुओं के एक जोड़े:

  • आप C99 और VLA उपयोग कर रहे हैं - चर लंबाई सरणियों - तो sizeof(vla) नहीं एक संकलन समय स्थिर है। सावधान रहें!
  • सी प्री-प्रोसेसर sizeof समझ में नहीं आता है जो एक उपद्रव है लेकिन तार्किक है। क्या हुआ अगर आवंटन पास के घोषणा करने के लिए नहीं है ..लेकिन

    foo **ff = malloc(count * sizeof *ff); 
    foo **gg = malloc(sizeof(foo*) * count); 
    

    :

+0

ऐसा लगता है कि आपको यहां एक और पूछे जाने योग्य प्रश्न मिल गया है। मेरी समझ आकार एक संकलन-समय की बात है, भले ही यह थोड़ी दिखती है और (लाइब्रेरी) फ़ंक्शन की तरह कार्य करती है। तो शायद वह अलग दिखना चाहता है। मैं इसे पदार्थ के लिए लागू नहीं करता हूं। फिर फिर से मैं "वापसी (एक्स);" करने से stares मिल गया है; – gbarry

+0

मैं अक्सर वापसी मूल्य के आसपास कोष्ठक का उपयोग करता हूं। मुझे पता है कि कुछ लोग उस पर परेशान हैं, लेकिन यह मेरे लिए काम करता है। मैं या तो 'कार्यों' के रूप में वापसी या आकार के बारे में उलझन में नहीं हूँ। –

+1

मुझे रिटर्न पर ब्रांड्स से नफरत है, ज्यादातर क्योंकि यह अनावश्यक है। आकार के बाद कोष्ठक होने से पठनीयता में मदद मिल सकती है: मॉलोक (आकार (* एफ) * 10) मॉलोक (आकार * एफ * 10) से समझना बहुत आसान है। – jmucchiello

4

आप इन के बीच थोड़ा अंतर देख सकते हैं? अगर मैं की तरह एक लाइन के पार चलो:

ff = realloc(ff, count * sizeof *ff); 

तो मैं काफी विश्वास है कि लाइन सही है कर रहा हूँ, यहाँ तक कि ff के प्रकार को याद के बिना। हालांकि, अगर मैं देख रहा हूँ इस:

ff = realloc(ff, count * sizeof(foo *)); 

तो मैं कुछ हद तक संदिग्ध हो सकती है, और ff के प्रकार के आराम से मेरे दिमाग डाल करने के लिए देखने के लिए की जरूरत है।

0

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

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

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

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