2013-06-23 4 views
39

में उपयोग करने के लिए यह देखते हुएक्यों यह सुरक्षित sizeof (* सूचक) malloc

struct node 
{ 
    int a; 
    struct node * next; 
}; 

एक नई संरचना malloc करने के लिए,

struct node *p = malloc(sizeof(*p)); 

struct node *p = malloc(sizeof(struct node)); 

क्यों अधिक सुरक्षित है? मैंने सोचा कि वे वही हैं।

+8

FYI करें, जब एक चर के साथ प्रयोग किया, 'sizeof' कोष्ठक की जरूरत नहीं है:' पी = malloc (sizeof * p); ' –

+52

यह और भी है माता-पिता के साथ पठनीय –

+5

@ टोमरएराजी: मैं अलग होना चाहता हूं; यह माता-पिता के साथ _less_ पठनीय है। माता-पिता के बिना, यह _cannot_ एक टाइपनाम है; माता-पिता की कमी मानव पाठक को असंबद्ध करने में मदद करती है। (मामूली समस्या: भी, माता-पिता सुझाव दे सकते हैं कि आकार एक कार्य है, जो यह नहीं है) – wildplasser

उत्तर

58

यह सुरक्षित है क्योंकि आपको दो बार टाइप नाम का उल्लेख नहीं करना है और इस प्रकार के "अस्वीकृत" संस्करण के लिए उचित वर्तनी नहीं बनाना है। उदाहरण के लिए, आप

int *****p = malloc(100 * sizeof *p); 

में "तारे गिनती" से तुलना करें कि की जरूरत नहीं है प्रकार के आधार पर

int *****p = malloc(100 * sizeof(int ****)); 

में sizeof जहां भी सुनिश्चित करें कि आप की सही संख्या का इस्तेमाल किया बनाना है *sizeof के तहत।

किसी अन्य प्रकार पर स्विच करने के लिए आपको केवल दो जगहों के बजाय एक स्थान (p की घोषणा) बदलनी होगी। और जिन लोगों के पास malloc के परिणाम कास्टिंग करने की आदत है, उन्हें तीन स्थानों को बदलना है।

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

उत्तरार्द्ध का अर्थ है: अनावश्यक जानवरों से बचें। अनावश्यक प्रकार-विशिष्ट निरंतर वाक्यविन्यास से बचें (जैसे 0.0 या 0L जहां एक सादा 0 पर्याप्त होगा)। sizeof के तहत प्रकार के नामों का उल्लेख करने से बचें। और इसी तरह।

+12

यह कुछ भी मूल्यवान नहीं है कि तथ्य यह है कि, जब प्रकार बदल जाता है, तो पी की घोषणा में इसे बदलना पर्याप्त होता है (इसे 'मॉलोक' में बदलने की कोई आवश्यकता नहीं होती है) न केवल इसका मतलब है कि कम काम है लेकिन वहां है त्रुटि का कम मौका। इस प्रकार, यह बग को कम करने में मदद करता है। –

+0

एंड्रीटी, मैं आपका बिंदु देखता हूं, संक्षेप में बोल रहा हूं ... लेकिन मैं आपको एक बियर शर्त लगाऊंगा, कभी भी कंप्यूटर के इतिहास में एक मंच नहीं रहा है जहां आकार (int ****)! = Sizeof (int ***):) – Josh

+0

@ जोश: आप मूल रूप से कह रहे हैं कि हर बार आपको सूचक आकार जानने की आवश्यकता होती है, तो आप केवल 'sizeof (double *) 'का उपयोग कर सकते हैं। हां, यह काम करेगा, लेकिन इस तरह की चीजें एक बेजोड़ बाएं कोष्ठक (http://xkcd.com/859/) के रूप में एक ही तरह का अनसुलझा तनाव उत्पन्न करना चाहिए – AnT

19

क्योंकि अगर समय p में कुछ बाद में किसी समय तो अपने स्मृति आवंटन malloc का उपयोग कर बयान बदलने के लिए नहीं है एक और संरचना प्रकार को इंगित करने के लिए किया जाता है, यह अभी भी काफी नया प्रकार के लिए आवश्यक स्मृति आवंटित करता है। यह सुनिश्चित करता है:

  • आप स्मृति आवंटन बयान हर बार जब आप प्रकार इसके लिए स्मृति आवंटित बदलने को संशोधित करने की जरूरत नहीं है।
  • आपका कोड अधिक मजबूत और मैन्युअल त्रुटियों के प्रति कम प्रवण है।

आम तौर पर ठोस प्रकारों पर भरोसा न करने के लिए हमेशा एक अच्छा अभ्यास होता है और पहला रूप यह करता है कि यह एक प्रकार का हार्ड कोड नहीं है।

3

यह सुविधाजनक है क्योंकि आप इस परिवर्तित कर सकते हैं:

struct node *p= malloc(sizeof(*p)); 
इस में

:

#define MALLOC(ptr) (ptr) = malloc(sizeof(*(ptr))) 

struct node *p; 
MALLOC(p); 

या, एक सरणी के लिए:

#define MALLOC_ARR(ptr, arrsize) \ 
     (ptr) = malloc(sizeof(*(ptr)) * arrsize) 

struct node *p; 
MALLOC_ARR(p, 20); 

और क्यों यह सुरक्षित है? चूंकि इन मैक्रोज़ का उपयोग करने वाले उपयोगकर्ता को स्ट्रेटिक सरणी के आकार को प्राप्त करने के लिए DIM() के मामले में एंड्रॉइड द्वारा उल्लिखित गलतियों को कम करने की संभावना कम होगी। क्योंकि उपयोगकर्ता स्थिर सरणी आकार कई स्थानों में सुसंगत बनाने के लिए की जरूरत नहीं है

#define DIM(arr) ((sizeof(arr))/(sizeof(arr[0]))) 

यह भी सुरक्षित है। सरणी आकार को एक ही स्थान पर सेट करें और फिर DIM() का उपयोग करें और आप कर चुके हैं! कंपाइलर आपके लिए इसका ख्याल रखता है।

0

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

typedef struct node 
{ 
    int a; 
    struct node * next; 
} node_t; 

तो फिर तुम यह कर सकते हैं:

node_t *p = malloc(sizeof(node_t)); 
संबंधित मुद्दे