क्या मैं मॉलॉक का परिणाम डाल सकता हूं?


2406

में इस सवाल का , किसी को एक में सुझाव दिया टिप्पणी है कि मैं चाहिए नहीं का परिणाम डाली malloc, यानी

int *sieve = malloc(sizeof(int) * length);

बजाय:

int *sieve = (int *) malloc(sizeof(int) * length);

ऐसा क्यों होगा?


221
इसके अलावा, छलनी लिखना अधिक उपयुक्त है = मालॉक (आकार * छलनी * लंबाई);
विलियम पर्ससेल


3
यहाँ उत्तर एकतरफा होने की खान हैं। उत्तर है, यह निर्भर करता है"। यह कार्यक्रम बनाने के लिए आवश्यक काम नहीं है। हालांकि कुछ कोडिंग मानकों की आवश्यकता होती है ... उदाहरण के लिए, CERT C कोडिंग स्टैंडर्ड देखें
डॉ। व्यक्ति व्यक्ति II

अजीब बात है, हर कोई इस बात से सहमत है कि आप मत डालें NULL। (शायद यही कारण है कि C ++ शुरू किया गया nullptr: C ++ किसी भी अनुमानित पॉइंटर कास्ट की अनुमति नहीं देता है)
नीलमणि_क्रीक

आप कर सकते हैं, लेकिन आपको इसकी आवश्यकता नहीं है। लेकिन आपको C ++ में जरूरत है।
नो बॉडी

जवाबों:


2215

नहीं ; आप परिणाम नहीं डालते हैं, क्योंकि:

  • यह अनावश्यक है, जैसा void *कि इस मामले में किसी भी अन्य पॉइंटर प्रकार के लिए स्वचालित रूप से और सुरक्षित रूप से पदोन्नत किया गया है।
  • यह कोड में अव्यवस्था जोड़ता है, जातियां पढ़ना बहुत आसान नहीं है (विशेषकर यदि सूचक प्रकार लंबा है)।
  • यह आपको खुद को दोहराता है, जो आमतौर पर बुरा होता है।
  • यदि आप शामिल करना भूल गए तो यह एक त्रुटि छिपा सकता है <stdlib.h>। इससे क्रैश (या इससे भी बदतर, कोड के कुछ पूरी तरह से अलग हिस्से में बाद में दुर्घटना का कारण नहीं बन सकता है)। विचार करें कि क्या होता है यदि संकेत और पूर्णांक अलग-अलग आकार के होते हैं; तब आप कास्टिंग द्वारा एक चेतावनी छिपा रहे हैं और अपने लौटे पते के बिट खो सकते हैं। नोट: C99 के रूप में निहित कार्य सी से चला गया है, और यह बिंदु अब प्रासंगिक नहीं है क्योंकि कोई भी स्वचालित धारणा नहीं है कि अघोषित कार्य वापस आते हैं int

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

यह भी ध्यान दें, जैसा कि टिप्पणीकार बताते हैं, कि ऊपर सी सीधे सी के बारे में बात करता है, सी ++ नहीं। मैं C और C ++ को अलग-अलग भाषाओं के रूप में बहुत दृढ़ता से मानता हूं।

आगे जोड़ने के लिए, आपका कोड अनावश्यक रूप से टाइप जानकारी ( int) को दोहराता है जो त्रुटियों का कारण बन सकता है। यह बेहतर है कि पॉइंटर को रिटर्न वैल्यू को स्टोर करने के लिए इस्तेमाल किया जा रहा है, दोनों को एक साथ "लॉक" करें:

int *sieve = malloc(length * sizeof *sieve);

यह भी lengthदृश्यता में वृद्धि के लिए सामने की ओर जाता है, और निरर्थक कोष्ठक के साथ चला जाता है sizeof; वे केवल तभी आवश्यक होते हैं जब तर्क एक प्रकार का नाम है। बहुत से लोगों को यह पता नहीं लगता (या अनदेखा) है, जो उनके कोड को अधिक क्रियाशील बनाता है। याद रखें: sizeofएक फ़ंक्शन नहीं है! :)


lengthमोर्चे पर जाने से कुछ दुर्लभ मामलों में दृश्यता बढ़ सकती है , किसी को इस बात पर भी ध्यान देना चाहिए कि सामान्य स्थिति में, इस तरह अभिव्यक्ति लिखना बेहतर होगा:

int *sieve = malloc(sizeof *sieve * length);

sizeofपहले रखने के बाद से , इस मामले में, यह सुनिश्चित करता है कि गुणा कम से कम size_tगणित के साथ किया जाता है ।

तुलना करें: malloc(sizeof *sieve * length * width)बनाम malloc(length * width * sizeof *sieve)दूसरा length * widthकब अतिप्रवाह कर सकता है widthऔर lengthतुलना में छोटे प्रकार के होते हैं size_t


21
कृपया जवाब अपडेट करने पर विचार करें। कलाकार अब खतरनाक नहीं है, और अपने आप को दोहराना कोई बुरी बात नहीं है (अतिरेक त्रुटियों को पकड़ने में मदद कर सकता है)।
एन। 'सर्वनाम' मी।

11
कंपाइलर बदल गए हैं। एक अप-टू-डेट कंपाइलर आपको मॉलॉक की एक लापता घोषणा के बारे में चेतावनी देगा।
एन। 'सर्वनाम' मी।

55
@nm ठीक है। मुझे लगता है कि यह मानना ​​बुरा है कि यहां पढ़ने वाले किसी भी व्यक्ति के पास एक विशेष संकलक है। इसके अलावा, C11 के बाद से पूरे "निहित कार्य" की अवधारणा समाप्त हो गई है, मुझे नहीं पता था। फिर भी, मैं एक व्यर्थ कलाकारों को जोड़ने में बिंदु नहीं देखता हूं। क्या आप भी int x = (int) 12;सिर्फ बातें स्पष्ट करने के लिए करते हैं?
खोलना

22
@nm यदि स्पष्ट रूप से एक शून्य सूचक "बग" को हल करने में मदद करता है, तो आपको अधिक संभावना है कि अपरिभाषित व्यवहार का सामना करना पड़ता है, जिसका अर्थ होगा कि प्रश्न में कार्यक्रम की संभावना बहुत खराब, अनदेखा बग है जिसे आपने अभी तक नहीं चलाया है। और एक दिन, एक ठंडी सर्दियों की शाम को, आप काम से घर आएंगे अपने GitHub पेज को खोजने के लिए समस्या के साथ बाढ़ आई जिसमें उपयोगकर्ताओं के नाक से बाहर उड़ने वाले राक्षसों के बारे में शिकायत की गई
ब्रैडेन सर्वश्रेष्ठ

12
@unwind यहां तक ​​कि मैं आपसे सहमत हूं, (int)12तुलनीय नहीं है। 12 है एक int, डाली बस कुछ नहीं करता है। का सूचक malloc()है void *, न कि सूचक प्रकार को कास्ट किया गया है। (अगर यह नहीं है void *। तो सादृश्य वह (int)12होगा (void*)malloc(…)जो कोई भी चर्चा नहीं कर रहा है।)
अमीन नेगम-अवाड

376

सी में, आपको रिटर्न वैल्यू डालने की जरूरत नहीं है malloc। द्वारा दिए गए शून्य को इंगित करने वाला सूचक mallocस्वचालित रूप से सही प्रकार में परिवर्तित हो जाता है। हालाँकि, यदि आप चाहते हैं कि आपका कोड C ++ कंपाइलर के साथ संकलित हो, तो एक कास्ट की जरूरत है। समुदाय के बीच एक पसंदीदा विकल्प निम्नलिखित का उपयोग करना है:

int *sieve = malloc(sizeof *sieve * length);

यदि इसके अलावा आप अभिव्यक्ति के दाहिने हाथ को बदलने के बारे में चिंता करने से मुक्त करते हैं, तो कभी भी आप के प्रकार को बदलते हैं sieve

जातियां खराब हैं, जैसा कि लोगों ने बताया है। खासकर पॉइंटर कास्ट।


71
@MAKZ मैं तर्क malloc(length * sizeof *sieve)देता sizeofहूं कि malloc(length * sizeof(*sieve))ऐसा लगता है कि यह एक परिवर्तनशील है - इसलिए मुझे लगता है कि यह अधिक पठनीय है।
माइकल एंडरसन

21
और malloc(length * (sizeof *sieve))अभी भी पठनीय है। IMHO।
टोबे स्पाइट

18
@ मिचेल एंडरसन ने ()एक तरफ ध्यान दिया, ध्यान दें कि आपकी सुझाई गई शैली ने क्रम को बदल दिया है। विचार करें कि जब तत्व गणना की गणना की जाती है length*width, तो sizeofपहले मामले को ध्यान में रखते हुए कम से कम size_tगणित के साथ गुणा किया जाता है । malloc(sizeof( *ptr) * length * width)बनाम की तुलना करें malloc(length * width * sizeof (*ptr))- length*widthजब width,lengthछोटे प्रकार होते हैं तो दूसरा अतिप्रवाह कर सकता है size_t
chux -

3
@chux यह स्पष्ट नहीं है, लेकिन जवाब को संपादित किया गया है ताकि मेरी टिप्पणी कम प्रासंगिक हो - मूल सुझाव थाmalloc(sizeof *sieve * length)
माइकल एंडरसन

12
C, C ++ नहीं है। यह कहते हुए कि वे अंततः भ्रम और उदासी का कारण बनेंगे। यदि आप C ++ का उपयोग कर रहे हैं, तो एक C- स्टाइल कास्ट भी खराब है (जब तक कि आप बहुत पुराने C ++ कंपाइलर का उपयोग नहीं कर रहे हैं)। और static_cast>()(या reinterpret_cast<>()) सी की किसी भी बोली के साथ संगत नहीं है
डेविड सी।

349

आप कास्ट करते हैं , क्योंकि:

  • यह आपके कोड को C और C ++ के बीच अधिक पोर्टेबल बनाता है , और SO अनुभव दिखाता है, कई महान प्रोग्रामर दावा करते हैं कि वे C में लिख रहे हैं जब वे वास्तव में C ++ (या C प्लस स्थानीय कंपाइलर एक्सटेंशन) में लिख रहे हैं।
  • ऐसा करने में असफल होना एक त्रुटि छिपा सकता है : type *बनाम लिखने के लिए भ्रमित करने के सभी SO उदाहरणों पर ध्यान दें type **
  • यह विचार कि यह आपको #includeएक उपयुक्त हेडर फ़ाइल में विफल होने से आपको सूचित करता है, पेड़ों के लिए जंगल याद करता है । यह कहने के समान है कि "इस तथ्य के बारे में चिंता न करें कि आप कंपाइलर को प्रोटोटाइप नहीं देखने के बारे में शिकायत करने में असफल रहे - कि pesky stdlib.h याद करने के लिए वास्तविक महत्वपूर्ण बात है!"
  • यह एक अतिरिक्त संज्ञानात्मक क्रॉस-चेक को बाध्य करता है । यह उस चर के कच्चे आकार के लिए आपके द्वारा किए जा रहे अंकगणित के ठीक बगल में (कथित) वांछित प्रकार डालता है। मुझे यकीन है कि आप एक एसओ अध्ययन कर सकते हैं जो दिखाता है कि malloc()जब एक डाली होती है तो बग बहुत तेजी से पकड़े जाते हैं। दावे के साथ, एनोटेशन जो इरादे प्रकट करते हैं, बग को कम करते हैं।
  • अपने आप को इस तरह से दोहराना कि मशीन अक्सर जाँच कर सकती है एक महान विचार है। वास्तव में, यह एक जोर है, और कलाकारों का यह प्रयोग एक जोर है। दावे अभी भी सबसे सामान्य तकनीक है जो हमारे पास कोड सही होने के लिए है, क्योंकि ट्यूरिंग इतने साल पहले इस विचार के साथ आया था।

39
@ulidtko यदि आप नहीं जानते हैं, तो यह कोड लिखना संभव है जो C और C ++ दोनों को संकलित करता है। वास्तव में अधिकांश हेडर फाइलें इस तरह की होती हैं, और उनमें अक्सर कोड (मैक्रो और इनलाइन फ़ंक्शन) होते हैं। दोनों को संकलित करने के लिए .c/ .cppफ़ाइल होने के कारण दोनों ही बहुत उपयोगी नहीं है, लेकिन एक मामला throwC ++ संकलक के साथ संकलित होने पर C ++ समर्थन जोड़ रहा है (लेकिन return -1;जब C संकलक के साथ संकलित किया जाता है, या जो भी हो)।
हाईड

37
यदि किसी के पास एक हेडर में मैलोडॉक कॉल इनलाइन है तो मैं प्रभावित नहीं होऊंगा, #ifdef __cplusplus और एक्सटर्नल "C" {} इस जॉब के लिए हैं, अतिरिक्त कास्ट्स में जोड़कर नहीं।
पौलएम

15
खैर, बिंदु 1 अप्रासंगिक है, सी! = सी ++ के बाद से, अन्य बिंदु भी तुच्छ हैं, यदि आप अपनी कॉल में चर का उपयोग करते mallocहैं: char **foo = malloc(3*sizeof(*foo));यदि काफी पूर्ण-प्रमाण: 3 पॉइंट टू चार पॉइंटर्स। फिर पाश, और करो foo[i] = calloc(101, sizeof(*(foo[i])));। 101 वर्णों का आबंटित सरणी, बड़े करीने से ज़ीरो के लिए प्रारंभिक। किसी कास्ट की जरूरत नहीं। unsigned charउस मामले के लिए घोषणा या किसी अन्य प्रकार को बदलें , और आप अभी भी अच्छे हैं
एलियास वान ओटगेम

34
जब मैंने सोचा कि मुझे मिल गया है, तो यह आता है! शानदार जवाब। इसके StackOverflow में पहली बार है कि मैं +1 दो विपरीत जवाब! +1 नहीं, आपने डाली नहीं, और +1 हां, आपने डाली! जबरदस्त हंसी। तुम लोग भयानक हो। और मेरे और मेरे छात्रों के लिए, मैंने अपना मन बनाया: मैं कास्ट करता हूं। कास्टिंग करते समय छात्र जिस तरह की त्रुटियां करते हैं, वे अधिक आसानी से देखी जाती हैं।
डॉ। बिको

15
@ लुशेंको: खुद को इस तरह से दोहराना कि मशीन द्वारा मान्य नहीं किया जा सकता है और न ही स्थानीय निरीक्षण खराब है। अपने आप को ऐसे तरीकों से दोहराना जो ऐसे साधनों द्वारा मान्य हो सकते हैं, कम बुरे हैं। यह देखते हुए struct Zebra *p; ... p=malloc(sizeof struct Zebra);, मॉलॉक पी के प्रकार के बारे में जानकारी से बचने से बच नहीं सकता है, लेकिन न तो संकलक और न ही स्थानीय कोड निरीक्षण किसी भी समस्या का पता लगाएगा यदि एक प्रकार बदल गया लेकिन दूसरा नहीं। यदि कोड p=(struct Zebra*)malloc(sizeof struct Zebra);प्रकार मैच नहीं करता है p, तो कोड को और कंपाइलर को बदल दें , और स्थानीय निरीक्षण से पता चलेगा ...
सुपरकैट

170

जैसा कि दूसरों ने कहा है, यह C के लिए आवश्यक नहीं है, लेकिन C ++ के लिए आवश्यक है। अगर आपको लगता है कि आप अपने C कोड को C ++ कंपाइलर के साथ संकलित करने जा रहे हैं, तो किन कारणों से, आप इसके बजाय मैक्रो का उपयोग कर सकते हैं, जैसे:

#ifdef __cplusplus
# define NEW(type, count) ((type *)calloc(count, sizeof(type)))
#else
# define NEW(type, count) (calloc(count, sizeof(type)))
#endif

इस तरह आप अभी भी इसे बहुत ही संक्षिप्त तरीके से लिख सकते हैं:

int *sieve = NEW(int, 1);

और यह C और C ++ के लिए संकलन करेगा।


17
चूंकि आप वैसे भी एक मैक्रो का उपयोग कर रहे हैं, आप newC ++ की परिभाषा में उपयोग क्यों नहीं करते हैं ?
होसम ऐली

63
क्योंकि ऐसा करने का कोई कारण नहीं है। यह मुख्य रूप से C प्रोग्राम्स के लिए है जो C ++ कंपाइलर के साथ संकलित हैं। यदि आप 'नए' का उपयोग करने जा रहे हैं, तो केवल एक चीज आपको मिल रही है। तुम तो मुक्त करने के लिए भी एक मैक्रो की जरूरत है। और आपको एक सरणी को खाली करने के लिए एक मैक्रो की जरूरत है, एक भेदभाव जो सी में मौजूद नहीं है
क्विनमार

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

86
@Hosam: हाँ, यह निश्चित रूप से है। यदि आप उपयोग करते हैं newतो आपको अवश्य उपयोग करना चाहिए deleteऔर यदि आप उपयोग करते हैं malloc()तो आपको अवश्य करना चाहिए free()। उन्हें कभी न मिलाएं।
ग्रीम पेरो

17
यदि कोई इस दृष्टिकोण को लेने जा रहा है, तो मैक्रो NEWको कॉल करना शायद एक बुरा विचार है क्योंकि संसाधन का उपयोग करके कभी नहीं लौटाया जाता है delete(या DELETE) इसलिए आप अपनी शब्दावली को मिला रहे हैं। इसके बजाय, इसका नामकरण MALLOC, या CALLOCइस मामले में, अधिक समझ में आता है।
महा

139

से विकिपीडिया :

कास्टिंग के लिए लाभ

  • कलाकारों को शामिल करने से सी प्रोग्राम या फ़ंक्शन को C ++ के रूप में संकलित करने की अनुमति मिल सकती है।

  • कलाकारों ने मूल रूप से 1989 के पूर्व संस्करणों के लिए अनुमति दी है जो मूल रूप से एक चार * लौटाता है।

  • कास्टिंग करने से डेवलपर को टाइप करने में विसंगतियों की पहचान करने में मदद मिल सकती है कि गंतव्य पॉइंटर प्रकार को बदलना चाहिए, खासकर यदि पॉइंटर को मॉलोक () कॉल से बहुत दूर घोषित किया जाता है (हालांकि आधुनिक कंपाइलर और स्टैटिक विश्लेषक इस प्रकार के व्यवहार पर चेतावनी दे सकते हैं बिना कलाकारों की आवश्यकता के)।

कास्टिंग के लिए नुकसान

  • एएनएसआई सी मानक के तहत, कास्ट बेमानी है।

  • हेडर stdlib.h को शामिल करने के लिए कलाकारों को जोड़ने में विफलता हो सकती हैजिसमें मॉलॉक के लिए प्रोटोटाइप पाया जाता है। मॉलोक के लिए एक प्रोटोटाइप की अनुपस्थिति में, मानक की आवश्यकता है कि सी संकलक मान लेता है कि मॉलॉक एक इंट रिटर्न देता है। यदि कोई कास्ट नहीं है, तो इस पूर्णांक को सूचक को सौंपा जाने पर एक चेतावनी जारी की जाती है; हालांकि, कलाकारों के साथ, इस चेतावनी का उत्पादन नहीं किया जाता है, बग को छिपाते हुए। कुछ आर्किटेक्चर और डेटा मॉडल (जैसे 64-बिट सिस्टम पर LP64, जहां लंबी और संकेत 64-बिट और इंट 32-बिट हैं) पर, यह त्रुटि वास्तव में अपरिभाषित व्यवहार में परिणाम कर सकती है, क्योंकि अंतर्निहित घोषित मॉलोक एक 32- देता है बिट मान जबकि वास्तव में परिभाषित फ़ंक्शन 64-बिट मान देता है। कॉलिंग कन्वेंशन और मेमोरी लेआउट के आधार पर, इसके परिणामस्वरूप स्टैक स्मैशिंग हो सकती है। इस मुद्दे को आधुनिक संकलक में किसी का ध्यान नहीं जाने की संभावना है, जैसा कि वे समान रूप से चेतावनी देते हैं कि एक अघोषित फ़ंक्शन का उपयोग किया गया है, इसलिए एक चेतावनी अभी भी दिखाई देगी। उदाहरण के लिए, जीसीसी का डिफ़ॉल्ट व्यवहार एक चेतावनी दिखाने के लिए है जो पढ़ता है कि "अंतर्निहित कार्य की असंगत अंतर्निहित घोषणा" यह ध्यान दिए बिना कि क्या मौजूद है या नहीं।

  • यदि पॉइंटर के प्रकार को इसकी घोषणा में बदल दिया जाता है, तो किसी को भी उन सभी लाइनों को बदलने की आवश्यकता हो सकती है, जहां मॉलोक कहा जाता है और डाली जाती है।

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

यानी: यदि आपको C प्रोग्राम को C ++ के रूप में संकलित करने की आवश्यकता है (हालाँकि यह एक अलग भाषा है) तो आपको उपयोग का परिणाम अवश्य डालना चाहिए malloc


1
क्या करता है " कास्टिंग डेवलपर को प्रकार में विसंगतियों की पहचान करने में मदद कर सकता है गंतव्य गंतव्य सूचक प्रकार को बदलना चाहिए, खासकर अगर सूचक malloc()कॉल से दूर घोषित किया जाता है " मतलब? क्या आप एक उदाहरण दे सकते हैं?
स्पिकट्रिक्स

3
@CoolGuy: किसी अन्य उत्तर पर पहले की टिप्पणी देखें । लेकिन ध्यान दें कि p = malloc(sizeof(*p) * count)मुहावरा स्वचालित रूप से परिवर्तनों को उठाता है, इसलिए आपको चेतावनी प्राप्त करने और कुछ भी बदलने की ज़रूरत नहीं है। तो यह एक वास्तविक लाभ नहीं है बनाम कास्टिंग के लिए सबसे अच्छा विकल्प नहीं है।
पीटर कॉर्ड्स

7
यह उचित उत्तर है: पेशेवरों और विपक्ष हैं, और यह स्वाद के मामले में उबलता है (जब तक कि कोड सी ++ के रूप में संकलन नहीं करना चाहिए - तब डाली अनिवार्य है)।
पीटर -

3
प्वाइंट 3 म्यूट है, क्योंकि यदि पॉइंटर के प्रकार को इसकी घोषणा में बदल दिया जाता है, तो किसी को मॉलॉक, रियललॉक और उस प्रकार को हल करने के हर उदाहरण की जांच करनी चाहिए। कास्टिंग आपको ऐसा करने के लिए मजबूर करेगा।
मिशैल रॉय

104

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


100

आप मॉलॉक का परिणाम नहीं देते हैं, क्योंकि ऐसा करने से आपके कोड में व्यर्थ अव्यवस्था बढ़ जाती है।

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

कुछ टिप्पणियां:

  • एक शून्य पॉइंटर को एक स्पष्ट कास्ट (सी 11 6.3.2.3 और 6.5.16.1) के बिना किसी अन्य पॉइंटर प्रकार से / में परिवर्तित किया जा सकता है।

  • C ++ हालांकि एक void*और सूचक प्रकार के बीच एक अंतर्निहित डाली की अनुमति नहीं देगा । तो C ++ में, कास्ट सही होता। लेकिन अगर आप C ++ में प्रोग्राम करते हैं, तो आपको newमॉलोक () का उपयोग करना चाहिए, न कि। और आपको C ++ कंपाइलर का उपयोग करके कभी भी C कोड संकलित नहीं करना चाहिए।

    यदि आपको समान स्रोत कोड के साथ C और C ++ दोनों का समर्थन करने की आवश्यकता है, तो मतभेदों को चिह्नित करने के लिए कंपाइलर स्विच का उपयोग करें। एक ही कोड के साथ दोनों भाषा मानकों को संप्रदाय करने का प्रयास न करें, क्योंकि वे संगत नहीं हैं।

  • यदि C कंपाइलर फ़ंक्शन नहीं ढूँढ पाता है क्योंकि आप हेडर को शामिल करना भूल गए हैं, तो आपको उसके बारे में कंपाइलर / लिंकर त्रुटि मिलेगी। इसलिए यदि आप इसे शामिल <stdlib.h>करना नहीं भूलते हैं तो यह कोई बड़ी बात नहीं है, आप अपना कार्यक्रम नहीं बना पाएंगे।

  • प्राचीन संकलक जो मानक के एक संस्करण का पालन करते हैं, जो 25 वर्ष से अधिक पुराना है, को शामिल करने के लिए भूल जाने <stdlib.h>से खतरनाक व्यवहार होगा। क्योंकि उस प्राचीन मानक में, एक दृश्य प्रोटोटाइप के बिना कार्यों ने स्पष्ट रूप से रिटर्न प्रकार को बदल दिया int। मालकॉक से परिणाम को स्पष्ट रूप से देखना इस बग को दूर कर देगा।

    लेकिन यह वास्तव में एक गैर-मुद्दा है। आप 25 साल पुराने कंप्यूटर का उपयोग नहीं कर रहे हैं, तो आप 25 साल पुराने कंपाइलर का उपयोग क्यों करेंगे?


9
"व्यर्थ अव्यवस्था" एक ऐसी अतिशयोक्ति है जो किसी को भी समझाने की संभावना को रोक देती है जो आपसे पहले से सहमत नहीं है। एक कलाकार निश्चित रूप से व्यर्थ नहीं है; रॉन बर्क और काज के जवाब कास्टिंग के पक्ष में तर्क देते हैं जिससे मैं बहुत सहमत हूं। क्या उन चिंताओं का वजन उन चिंताओं से अधिक है जिनका आप उल्लेख करना उचित सवाल पूछना चाहते हैं। मेरे लिए, आपकी चिंता उनकी तुलना में अपेक्षाकृत कम दिखती है।
डॉन हैच

"शून्य सूचक को बिना किसी स्पष्ट कलाकार के किसी भी अन्य सूचक प्रकार से / में परिवर्तित किया जा सकता है" 6.3.2.3 द्वारा समर्थित नहीं है। शायद आप "किसी वस्तु प्रकार के सूचक" के बारे में सोच रहे हैं? "शून्य पॉइंटर" और "पॉइंटर टू ए फंक्शन" इतनी आसानी से परिवर्तनीय नहीं हैं।
chux -

वास्तव में संदर्भ अधूरा था। "निहितार्थ" के लिए प्रासंगिक भाग सरल असाइनमेंट 6.5.16.1 का नियम है। "एक ऑपरेंड एक ऑब्जेक्ट प्रकार के लिए एक पॉइंटर है, और दूसरा एक योग्य या अयोग्य संस्करण के लिए एक पॉइंटर है"। मैंने इस संदर्भ को पूर्णता के उत्तर में जोड़ दिया है।
लंडिन

91

C में आपको void *किसी अन्य (डेटा) पॉइंटर से एक अंतर्निहित रूपांतरण मिलता है ।


6
@ जैन: ठीक है, शायद अधिक उचित शब्द "निहित रूपांतरण" है। जैसे फ्लोटिंग पॉइंट एक्सप्रेशन में इंटीग्रल वैरिएबल का उपयोग।
EFraim

@ एफ़्रेइम वास्तव में एक डाली में परिणाम होगा, और उस पर एक निहित होगा।
मैड फिजिसिस्ट

71

malloc()अब तक दिए गए मान को कास्टिंग करना आवश्यक नहीं है, लेकिन मैं एक बिंदु जोड़ना चाहूंगा जो लगता है कि किसी ने इंगित नहीं किया है:

प्राचीन दिनों में, यानी, एएनएसआई सी पहले void *सामान्य प्रकार के संकेत प्रदान करता है , char *इस तरह के उपयोग के लिए प्रकार है। उस स्थिति में, कलाकार कंपाइलर चेतावनी को बंद कर सकता है।

संदर्भ: सी एफएक्यू


2
कंपाइलर चेतावनियों को बंद करना एक बुरा विचार है।
अल्बर्ट वैन डेर होर्स्ट

8
@AlbertvanderHorst यदि आप ऐसा नहीं कर रहे हैं तो सटीक समस्या को हल करके आपको चेतावनी देने के लिए चेतावनी है।
डैन बेहार्ड

@ दन। यदि सटीक समस्या को हल करने का मतलब है कि * * के बजाय आधुनिक ANSI C प्रकारों को वापस करने के लिए एक सबरूटीन का पुनर्लेखन किया जाए, तो मैं सहमत हूं। मैं कॉल नहीं करूंगा कि कंपाइलर बंद हो जाए। उन प्रबंधकों को न दें जो इस बात पर जोर देते हैं कि कोई कंपाइलर चेतावनी नहीं है, इसके बजाय संभावित समस्याओं का पता लगाने के लिए प्रत्येक पुनर्संयोजन द्वारा उनका उपयोग करें। Groetjes अल्बर्ट
Albert van der Horst

53

बस अपने अनुभव को जोड़ते हुए, कंप्यूटर इंजीनियरिंग का अध्ययन करते हुए मैं देखता हूं कि मैंने जिन दो या तीन प्रोफेसरों को सी में लिखा है, उन्होंने हमेशा मल्लोक को लिखा है, हालांकि मैंने जो पूछा (सीवी और सीवी की समझ के साथ) ने मुझे बताया कि यह बिल्कुल अनावश्यक है लेकिन केवल बिल्कुल विशिष्ट हुआ करता था, और छात्रों को बिल्कुल विशिष्ट होने की मानसिकता में लाने के लिए। अनिवार्य रूप से कास्टिंग कुछ भी नहीं बदलेगी कि यह कैसे काम करता है, यह वही करता है जो यह कहता है, मेमोरी आवंटित करता है, और कास्टिंग का प्रभाव नहीं पड़ता है, आपको एक ही मेमोरी मिलती है, और भले ही आप इसे गलती से किसी और को डाल दें (और किसी तरह से कम्पाइलर को मिटा दें त्रुटियाँ) C इसे उसी तरह एक्सेस करेगा।

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


3
पहले से ही उल्लेख के अलावा, कलाकार कीड़े को छिपा सकते हैं और संकलक या स्थिर विश्लेषक का विश्लेषण करने के लिए कोड को कठिन बना सकते हैं।
लुंडिन

2
"अनिवार्य रूप से कास्टिंग कुछ भी नहीं बदलेगी कि यह कैसे काम करता है"। मिलान प्रकार के लिए कास्टिंग कुछ भी नहीं बदलना चाहिए, लेकिन क्या var के प्रकार को बदलना चाहिए और कलाकारों का मिलान नहीं होना चाहिए, क्या समस्याएं आ सकती हैं? IWOs, कास्ट और var प्रकार को सिंक में रखा जाना चाहिए - दो बार रखरखाव का काम।
chux -

मैं देख सकता हूं कि प्रोफेसर कास्टिंग क्यों पसंद करते हैं। कास्टिंग एक शैक्षिक दृष्टिकोण से उपयोगी हो सकता है जहां यह प्रशिक्षक की जानकारी को बताता है और छात्र कोड को बनाए रखने की आवश्यकता नहीं है - इसका फेंक-दूर कोड। फिर भी एक कोडिंग, सहकर्मी-समीक्षा और रखरखाव के दृष्टिकोण से, p = malloc(sizeof *p * n);इतना सरल और बेहतर है।
chux -

53

के परिणामों को डालना अनिवार्य नहीं है malloc, क्योंकि यह वापस लौटता है void*, और void*किसी भी डेटाटाइप को इंगित किया जा सकता है।


34

एक शून्य पॉइंटर जेनेरिक ऑब्जेक्ट पॉइंटर है और सी एक शून्य पॉइंटर प्रकार से अन्य प्रकारों में निहित रूपांतरण का समर्थन करता है, इसलिए इसे स्पष्ट रूप से टाइपकास्ट करने की कोई आवश्यकता नहीं है।

हालांकि, यदि आप चाहते हैं कि समान कोड काम सी ++ प्लेटफॉर्म पर पूरी तरह से संगत हो, जो निहित रूपांतरण का समर्थन नहीं करता है, तो आपको टाइपकास्टिंग करने की आवश्यकता है, इसलिए यह सब प्रयोज्य पर निर्भर करता है।


2
यह सी और सी ++ दोनों के रूप में एक एकल स्रोत को संकलित करने के लिए एक सामान्य उपयोग का मामला नहीं है (जैसा कि विरोध किया गया है, कहते हैं, सी और सी ++ कोड को एक साथ लिंक करने के लिए घोषणाओं वाले हेडर फ़ाइल का उपयोग करके)। mallocC ++ में दोस्तों का उपयोग करना एक अच्छा चेतावनी संकेत है कि यह विशेष ध्यान देने योग्य है (या C में फिर से लिखना)।
टोबी स्पाईट

1
"एक शून्य सूचक एक जेनेरिक पॉइंटर है" -> "एक शून्य पॉइंटर एक जेनेरिक ऑब्जेक्ट पॉइंटर है"। फ़ंक्शन पॉइंटर्स का आकार अधिक हो सकता है void *, इस प्रकार void *फ़ंक्शन पॉइंटर को अच्छी तरह से स्टोर करने के लिए अपर्याप्त है।
chux - मोनिका

उस लाइन का मेरा इरादा वही था लेकिन फिर भी सुझाव के लिए धन्यवाद @chux।
एंडेवर

33

यह GNU C लाइब्रेरी रेफरेंस मैनुअल कहता है:

आप mallocकिसी भी सूचक चर के परिणाम को बिना कास्ट के स्टोर कर सकते हैं , क्योंकि आईएसओ सी स्वचालित रूप से void *आवश्यक होने पर टाइप को दूसरे प्रकार के पॉइंटर में कनवर्ट करता है। लेकिन कलाकारों को असाइनमेंट ऑपरेटरों के अलावा अन्य संदर्भों में आवश्यक है या यदि आप चाहते हैं कि आपका कोड पारंपरिक सी में चले।

और वास्तव में ISO C11 मानक (p347) ऐसा कहता है:

यदि आबंटन सफल हो जाता है तो पॉइंटर लौटाया जाता है, ताकि यह एक संरेखण के लिए किसी मूलभूत प्रकार की आवश्यकता के साथ किसी पॉइंटर को सौंपा जा सके और तब अंतरिक्ष में इस तरह की वस्तु या ऐसी वस्तुओं का उपयोग किया जा सके जब तक कि आबंटित न हो जाए। अंतरिक्ष को स्पष्ट रूप से निपटाया गया है)


31

लौटा हुआ प्रकार शून्य है *, जिसे वांछित प्रकार के डेटा पॉइंटर में डाला जा सकता है ताकि वे निष्क्रिय हो सकें।


1
void* वांछित प्रकार के लिए डाला जा सकता है, लेकिन ऐसा करने की कोई आवश्यकता नहीं है क्योंकि यह स्वचालित रूप से परिवर्तित हो जाएगा। इसलिए कास्ट आवश्यक नहीं है, और वास्तव में उच्च स्कोरिंग उत्तरों में वर्णित कारणों के लिए अवांछनीय है।
स्पाइट

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

28

सी भाषा में, एक शून्य पॉइंटर को किसी भी पॉइंटर को सौंपा जा सकता है, यही कारण है कि आपको एक प्रकार के कलाकारों का उपयोग नहीं करना चाहिए। यदि आप "सुरक्षित प्रकार" आवंटन चाहते हैं, तो मैं निम्नलिखित मैक्रो फ़ंक्शंस की सिफारिश कर सकता हूं, जो मैं हमेशा अपनी सी परियोजनाओं में उपयोग करता हूं:

#include <stdlib.h>
#define NEW_ARRAY(ptr, n) (ptr) = malloc((n) * sizeof *(ptr))
#define NEW(ptr) NEW_ARRAY((ptr), 1)

इन जगह के साथ आप बस कह सकते हैं

NEW_ARRAY(sieve, length);

गैर-गतिशील सरणियों के लिए, तीसरे में फ़ंक्शन मैक्रो है

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

जो सरणी लूप को सुरक्षित और अधिक सुविधाजनक बनाता है:

int i, a[100];

for (i = 0; i < LEN(a); i++) {
   ...
}

"एक शून्य पॉइंटर को किसी भी ऑब्जेक्ट पॉइंटर को सौंपा जा सकता है " फ़ंक्शन पॉइंटर्स एक और मुद्दा है, भले ही कोई malloc()भी नहीं हो ।
chux

void*फ़ंक्शन पॉइंटर से a / to असाइन करना जानकारी खो सकता है इसलिए "void पॉइंटर को किसी भी पॉइंटर को सौंपा जा सकता है," उन मामलों में एक समस्या है। किसी भी ऑब्जेक्ट पॉइंटर void*से ए , असाइन malloc()करना कोई समस्या नहीं है।
chux -

doपाश अभी तक एक पाश से जुड़े मैक्रो कि शीर्षक सवाल से दूर सोच रहा है से संबंधित टिप्पणी। उस टिप्पणी को हटाना। इसे बाद में भी नीचे ले जाएगा।
chux -

27

यह प्रोग्रामिंग लैंग्वेज और कंपाइलर पर निर्भर करता है। यदि आप mallocC में उपयोग करते हैं , तो इसे टाइप करने की कोई आवश्यकता नहीं है, क्योंकि यह स्वचालित रूप से कास्ट टाइप करेगा। हालांकि, यदि आप C ++ का उपयोग कर रहे हैं, तो आपको कास्ट टाइप करना चाहिए क्योंकि mallocएक void*प्रकार वापस आ जाएगा ।


1
फ़ंक्शन मॉलोक सी में एक शून्य सूचक लौटाता है लेकिन भाषा के नियम C ++ से अलग हैं।
अगस्त कार्लस्ट्रोम

16

जीसीसी और क्लैंग के लिए इस्तेमाल किए जाने वाले लोग खराब हो गए हैं। यह सब अच्छा नहीं है।

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

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

वर्तमान मानकों के तहत यह तर्क आवश्यक नहीं है। लेकिन वह तर्क वास्तविक दुनिया की व्यावहारिकताओं को छोड़ देता है। हम विशेष रूप से दिन के मानक द्वारा शासित दुनिया में कोड नहीं करते हैं, लेकिन मैं "स्थानीय प्रबंधन के वास्तविकता क्षेत्र" को कॉल करना पसंद करता हूं। और यह तुला और अंतरिक्ष समय से अधिक मुड़ गया था। :-)

YMMV।

मैं एक रक्षात्मक ऑपरेशन के रूप में मॉलोक कास्टिंग के बारे में सोचता हूं। न सुंदर, न सही, बल्कि आम तौर पर सुरक्षित। (ईमानदारी से, अगर आप stdlib.h तो शामिल नहीं किया है आपने जिस तरह से malloc कास्टिंग की तुलना में अधिक समस्याओं!)।


15

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

double d;
void *p = &d;
int *q = p;

मैं चाहता हूं कि अस्तित्व में नहीं था (और यह C ++ में नहीं है) और इसलिए मैंने कास्ट किया। यह मेरे स्वाद और मेरी प्रोग्रामिंग राजनीति का प्रतिनिधित्व करता है। मैं न केवल एक सूचक कास्ट कर रहा हूं, बल्कि प्रभावी रूप से, एक बैलट कास्ट कर रहा हूं, और मूर्खता के राक्षसों को बाहर निकाल रहा हूं । अगर मैं वास्तव में मूर्खता नहीं कर सकता , तो कम से कम मुझे विरोध के एक इशारे के साथ ऐसा करने की इच्छा व्यक्त करें।

वास्तव में, एक अच्छा अभ्यास उन mallocकार्यों के साथ लपेटना (और दोस्तों) है जो वापस आते हैं unsigned char *, और मूल रूप void *से आपके कोड में उपयोग करने के लिए कभी नहीं । आप एक सामान्य सूचक करने वाली किसी भी वस्तु की जरूरत है, एक का उपयोग char *या unsigned char *, और दोनों दिशाओं में डाले है। एक छूट, जो लिप्त हो सकती है, शायद, जैसे कार्यों का उपयोग कर रहा है memsetऔर memcpyबिना कलाकारों के।

कास्टिंग और C ++ संगतता के विषय पर, यदि आप अपना कोड लिखते हैं ताकि यह C और C ++ दोनों के रूप में संकलित हो (जिस स्थिति में आपको इसकेmalloc अलावा किसी अन्य चीज़ को असाइन करते समय रिटर्न वैल्यू डालनी पड़ेvoid * ), तो आप बहुत मदद कर सकते हैं खुद के लिए बात: आप कास्टिंग के लिए मैक्रोज़ का उपयोग कर सकते हैं जो C ++ के रूप में संकलित होने पर C ++ शैली की कास्ट में अनुवाद करते हैं, लेकिन C के रूप में संकलित होने पर C कास्ट में कमी करते हैं:

/* In a header somewhere */
#ifdef __cplusplus
#define strip_qual(TYPE, EXPR) (const_cast<TYPE>(EXPR))
#define convert(TYPE, EXPR) (static_cast<TYPE>(EXPR))
#define coerce(TYPE, EXPR) (reinterpret_cast<TYPE>(EXPR))
#else
#define strip_qual(TYPE, EXPR) ((TYPE) (EXPR))
#define convert(TYPE, EXPR) ((TYPE) (EXPR))
#define coerce(TYPE, EXPR) ((TYPE) (EXPR))
#endif

यदि आप इन मैक्रोज़ का पालन करते हैं, तो grepइन पहचानकर्ताओं के लिए आपके कोड आधार की एक सरल खोज आपको दिखाएगी कि आपके सभी कलाकार कहां हैं, इसलिए आप समीक्षा कर सकते हैं कि उनमें से कोई गलत है या नहीं।

फिर, आगे बढ़ते हुए, यदि आप नियमित रूप से C ++ के साथ कोड संकलित करते हैं, तो यह एक उपयुक्त कलाकारों के उपयोग को लागू करेगा। उदाहरण के लिए, आप का उपयोग करता है, तो strip_qualएक को दूर बस के लिए constया volatile, लेकिन इस तरह से कि एक प्रकार रूपांतरण अब शामिल है में कार्यक्रम के बदलाव, क्या आप नैदानिक मिल जाएगा, और आप डाले के संयोजन का उपयोग करने के लिए वांछित रूपांतरण प्राप्त करना होगा।

इन मैक्रोज़ का पालन करने में आपकी सहायता करने के लिए, GNU C ++ (C नहीं!) संकलक की एक सुंदर विशेषता है: एक वैकल्पिक निदान जो C शैली की सभी घटनाओं के लिए उत्पन्न होता है।

     -गोल्ड-स्टाइल-कास्ट (सी ++ और ऑब्जेक्टिव-सी ++ केवल)
         यदि कोई पुरानी शैली (सी-शैली) एक गैर-शून्य प्रकार के लिए डाली जाती है तो चेतावनी दी जाती है
         C ++ प्रोग्राम के भीतर। नई शैली की जातियां (डायनामिक_कास्ट,
         static_cast, reinterpret_cast, और const_cast) कम असुरक्षित हैं
         अनपेक्षित प्रभावों और खोजने के लिए बहुत आसान है।

यदि आपका C कोड C ++ के रूप में संकलित होता है, तो आप इस -Wold-style-castविकल्प का उपयोग (type)कास्टिंग सिंटैक्स की सभी घटनाओं का पता लगाने के लिए कर सकते हैं जो कोड में रेंग सकते हैं, और इन डायग्नॉस्टिक्स का अनुसरण करके उपरोक्त मैक्रोज़ (या) में से एक उपयुक्त विकल्प के साथ प्रतिस्थापित कर सकते हैं। संयोजन, यदि आवश्यक हो)।

रूपांतरण का यह उपचार "क्लीन सी" में काम करने के लिए एकल सबसे बड़ा स्टैंडअलोन तकनीकी औचित्य है: संयुक्त सी और सी ++ बोली, जो बदले में तकनीकी रूप से रिटर्न वैल्यू के कास्टिंग को सही ठहराते हैं malloc


जैसा कि अन्य ने बताया है, मैं आमतौर पर C और C ++ कोड नहीं मिलाने की सलाह दूंगा। हालांकि, यदि आपके पास इसे करने का अच्छा कारण है, तो मैक्रोज़ उपयोगी हो सकते हैं।
फिल 1970

@ Phil1970 यह सब एक एकजुट बोली में लिखा गया है, जो C और C ++ कंपाइलर के लिए पोर्टेबल होता है, और C ++ की कुछ क्षमताओं का लाभ उठाता है। इसे सभी को C ++ के रूप में संकलित किया जाना चाहिए, अन्यथा सभी C
कज़

यानी जो मैं पिछली टिप्पणी में कहना चाह रहा था वह यह है कि इसमें C और C ++ का मिश्रण नहीं है। आशय यह है कि कोड सभी को C के रूप में संकलित किया गया है या सभी C ++ के रूप में संकलित किया गया है।
काज

15

जब भी संभव हो C में प्रोग्रामिंग करते समय सबसे अच्छी बात:

  1. अपने प्रोग्राम को C कंपाइलर के माध्यम से सभी चेतावनियों को चालू करें -Wallऔर सभी त्रुटियों और चेतावनियों को ठीक करें
  2. सुनिश्चित करें कि वहाँ कोई चर के रूप में घोषित कर रहे हैं auto
  3. फिर इसे C ++ कंपाइलर का उपयोग करके संकलित करें -Wallऔर -std=c++11। सभी त्रुटियों और चेतावनियों को ठीक करें।
  4. अब फिर से सी कंपाइलर का उपयोग कर संकलन करें। आपके कार्यक्रम को अब बिना किसी चेतावनी के संकलित करना चाहिए और कम बग्स होना चाहिए।

यह प्रक्रिया आपको C ++ सख्त प्रकार की जाँच का लाभ उठाने देती है, इस प्रकार बग्स की संख्या को कम करती है। विशेष रूप से, यह प्रक्रिया आपको सम्मिलित करने के लिए बाध्य करती है stdlib.hया आपको मिल जाएगी

malloc इस दायरे में घोषित नहीं किया गया था

और आपको परिणाम mallocप्राप्त करने के लिए मजबूर करता है या आपको मिलेगा

से अवैध रूपांतरण void*करने के लिएT*

या आपका लक्ष्य प्रकार क्या है।

C ++ के बजाय C में लिखने से एकमात्र लाभ मुझे मिल सकता है

  1. C में एक अच्छी तरह से निर्दिष्ट ABI है
  2. C ++ अधिक कोड उत्पन्न कर सकता है [अपवाद, RTTI, टेम्प्लेट, रनटाइम बहुरूपता]

ध्यान दें कि स्थैतिक पॉलीमॉर्फिक सुविधा के साथ सबसे आम सी का उपयोग करते समय आदर्श मामले में दूसरा विपक्ष गायब हो जाना चाहिए ।

उन लोगों के लिए जो C ++ के सख्त नियमों को असुविधाजनक पाते हैं, हम C ++ 11 फीचर का उपयोग इनफर्ट प्रकार के साथ कर सकते हैं

auto memblock=static_cast<T*>(malloc(n*sizeof(T))); //Mult may overflow...

18
C कोड के लिए C कंपाइलर का उपयोग करें। C ++ कोड के लिए C ++ कंपाइलर का उपयोग करें। नहीं अगर नहीं, लेकिन नहीं। C ++ में अपने C कोड को फिर से लिखना पूरी तरह से एक और बात है, और हो सकता है - या नहीं - समय और जोखिमों के लायक।
टोबी स्पाइट

2
मैं @TobySpeight सलाह में जोड़ना चाहूंगा: यदि आपको C ++ प्रोजेक्ट में C कोड का उपयोग करने की आवश्यकता है, तो आप आमतौर पर C कोड को C (जैसे gcc -c c_code.c), C ++ कोड को C ++ (जैसे g++ -c cpp_code.cpp) के रूप में संकलित कर सकते हैं , और फिर उन्हें एक साथ लिंक कर सकते हैं। (जैसे gcc c_code.o cpp_code.oया निर्भरता परियोजना निर्भरता के आधार पर)। अब किसी भी भाषा की अच्छी विशेषताओं से खुद को वंचित करने का कोई कारण नहीं होना चाहिए ...
ऑटिस्टिक

1
@ user877329 यह कोड को जोड़ने के लिए श्रमसाध्य रूप से जोड़ने वाले श्रमसाध्य विकल्प का एक और अधिक समझदार विकल्प है, केवल "सी ++ संगत" होने के लिए, कोड की सुगमता को कम करता है।
ऑटिस्टिक

1
संभवतः इस संदर्भ में मुख्य लाभ यह है कि C आपको लिखने देता है p = malloc(sizeof(*p));, जिसे pकिसी भिन्न प्रकार के नाम में परिवर्तन करने पर पहली जगह बदलने की आवश्यकता नहीं है । कास्टिंग का प्रस्तावित "लाभ" यह है कि यदि आप pगलत प्रकार के हैं, तो आपको एक संकलन त्रुटि मिलती है , लेकिन यह बेहतर है अगर यह काम करता है।
पीटर कॉर्ड्स

1
मैं यह उल्लेख करना चाहूंगा कि उचित C ++ कंपाइलरों की कमी वाले प्लेटफार्मों को लक्षित करते समय C में लिखना आवश्यक हो सकता है। अपवाद और टेम्पलेट ऐसी विशेषताएं हैं जो आम तौर पर C ++ को छोटे और / या अधिक कुशल कोड बनाने में मदद करती हैं जबकि C ++ में रनटाइम पॉलीमॉर्फिज्म ज्यादातर सी के बराबर होता है
user7860670

15

नहीं, आपने परिणाम नहीं डाला है malloc()

सामान्य तौर पर, आप या से नहीं आते हैंvoid *

ऐसा न करने के लिए दिया गया एक विशिष्ट कारण यह है कि असफलता पर #include <stdlib.h>किसी का ध्यान नहीं जा सकता। यह एक लंबे समय के लिए अब कोई समस्या नहीं है क्योंकि C99 ने अंतर्निहित फ़ंक्शन घोषणाओं को अवैध बना दिया है , इसलिए यदि आपका कंपाइलर कम से कम C99 के अनुरूप है, तो आपको एक नैदानिक ​​संदेश मिलेगा।

लेकिन अनावश्यक पॉइंटर कास्ट न करने का एक बहुत मजबूत कारण है :

सी में, एक सूचक डाली लगभग हमेशा एक त्रुटि होती है । यह निम्नलिखित नियम ( N1570 में §6.5 p7 , C11 के लिए नवीनतम ड्राफ्ट) के कारण है:

एक वस्तु का संग्रहित मूल्य केवल एक लैवल्यू एक्सप्रेशन द्वारा एक्सेस किया जाता है, जिसमें निम्न में से एक प्रकार होता है:
- एक प्रकार की वस्तु के प्रभावी प्रकार के साथ संगत,
- एक प्रकार का एक योग्य संस्करण जो प्रभावी प्रकार के ऑब्जेक्ट के साथ संगत होता है,
- एक प्रकार जो कि ऑब्जेक्ट के प्रभावी प्रकार के अनुसार हस्ताक्षरित या अहस्ताक्षरित प्रकार है,
- एक प्रकार जो हस्ताक्षरित या अहस्ताक्षरित प्रकार वस्तु के प्रभावी प्रकार के एक योग्य संस्करण के अनुरूप है,
- एक समग्र या संघ प्रकार जिसमें एक शामिल है इसके सदस्यों के बीच पूर्वोक्त प्रकारों में (सहित, पुनरावर्ती, उपसमूह या निहित संघ का सदस्य), या
- एक चरित्र प्रकार।

इसे सख्त अलियासिंग नियम के रूप में भी जाना जाता है । तो निम्न कोड अपरिभाषित व्यवहार है :

long x = 5;
double *p = (double *)&x;
double y = *p;

और, कभी-कभी आश्चर्यजनक रूप से, निम्नलिखित भी है:

struct foo { int x; };
struct bar { int x; int y; };
struct bar b = { 1, 2};
struct foo *p = (struct foo *)&b;
int z = p->x;

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

tl; डॉ

संक्षेप में: क्योंकि सी में, पॉइंटर कास्ट की किसी भी घटना को विशेष ध्यान देने की आवश्यकता वाले कोड के लिए लाल झंडा उठाना चाहिए, आपको कभी भी अनावश्यक पॉइंटर कास्ट नहीं लिखना चाहिए ।


साइड नोट्स:

  • ऐसे मामले हैं जहां आपको वास्तव में कलाकारों की आवश्यकता होती है void *, उदाहरण के लिए यदि आप एक पॉइंटर प्रिंट करना चाहते हैं:

    int x = 5;
    printf("%p\n", (void *)&x);

    यहां कास्ट आवश्यक है, क्योंकि printf()एक वैरिएड फ़ंक्शन है, इसलिए निहित रूपांतरण काम नहीं करते हैं।

  • C ++ में, स्थिति अलग है। व्युत्पन्न वर्गों की वस्तुओं के साथ काम करते समय कास्टिंग सूचक प्रकार कुछ सामान्य (और सही) हैं। इसलिए, यह समझ में आता है कि C ++, करने के लिए और से रूपांतरण void *है नहीं निहित। C ++ में कास्टिंग के विभिन्न स्वादों का एक पूरा सेट है।


1
आपके उदाहरणों में आप शून्य * से बचते हैं। डबल * से इंट * और इसके विपरीत कास्ट के बीच अंतर है। मॉलोक रिटर्न पॉइंटल सबसे बड़े मानक प्रकार से जुड़ा हुआ है, इसलिए कोई भी अन्य नियम नहीं तोड़े जाते हैं भले ही कोई व्यक्ति इस गठबंधन सूचक को अन्य प्रकार से बनाता हो।
P__J__

एलियासिंग है कुछ भी नहीं है आपको स्पष्ट रूप से बात नहीं मिला - सब पर संरेखण के साथ और अपनी टिप्पणी के बाकी के लिए क्या करना है।

@PeterJ: केवल मामले में, बिंदु एक अनावश्यक पॉइंटर कास्ट से बचने के लिए है , इसलिए यह कोड के एक टुकड़े की तरह नहीं दिखता है जिस पर आपको विशेष ध्यान देना है।

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

बल्कि, आपको सभी सूचक कलाकारों पर प्रतिबंध लगाने के लिए एक नियम बनाना होगा। लेकिन तब आप क्रमांकन दिनचर्या और हार्डवेयर-संबंधी प्रोग्रामिंग जैसी चीजें कैसे लिखेंगे? चीजें जो सी की ताकत हैं। ऐसी जातियां ठीक हैं यदि आप जानते हैं कि आप क्या कर रहे हैं।
लुंडिन

15

मैं कलाकारों को करना पसंद करता हूं, लेकिन मैन्युअल रूप से नहीं। मेरा पसंदीदा उपयोग कर रहा है g_newऔर g_new0मैक्रब से glib है। यदि ग्लिब का उपयोग नहीं किया जाता है, तो मैं इसी तरह के मैक्रोज़ जोड़ूंगा। वे मैक्रोज़ प्रकार की सुरक्षा से समझौता किए बिना कोड दोहराव को कम करते हैं। यदि आप टाइप गलत करते हैं, तो आपको गैर-शून्य पॉइंटर्स के बीच एक निहित कास्ट मिलेगा, जो चेतावनी का कारण होगा (C ++ में त्रुटि)। यदि आप उस शीर्ष लेख को शामिल करना भूल जाते हैं जो परिभाषित करता है g_newऔर g_new0, आपको एक त्रुटि मिलेगी। g_newऔर g_new0दोनों एक ही तर्क लेते हैं, इसके विपरीत mallocउससे कम तर्क लेते हैं calloc। बस 0शून्य-आरंभिक मेमोरी प्राप्त करने के लिए जोड़ें । कोड को बिना परिवर्तन के C ++ कंपाइलर के साथ संकलित किया जा सकता है।


12

कास्टिंग केवल C ++ के लिए नहीं है C. यदि आप C ++ कंपाइलर का उपयोग कर रहे हैं तो आप इसे C कंपाइलर में बेहतर रूप से बदलते हैं।


9

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


11
" यह अनिवार्य नहीं है - हालांकि आपको इसे करना चाहिए " - मुझे लगता है कि वहां एक विरोधाभास है!
टोबी स्पाइट

5
मुझे लगता है कि आपको इस पोस्ट को किसी को पढ़ना चाहिए, और देखें कि क्या वे समझते हैं कि आप क्या कहना चाह रहे हैं। फिर इसे फिर से लिखना, यह स्पष्ट करना कि आप क्या कहना चाहते हैं। मैं वास्तव में नहीं समझ सकता कि आपका जवाब क्या है।
बिल वुडगेर

9

एक शून्य पॉइंटर एक जेनेरिक पॉइंटर है और सी एक शून्य पॉइंटर प्रकार से अन्य प्रकारों में निहित रूपांतरण का समर्थन करता है, इसलिए इसे स्पष्ट रूप से टाइपकास्ट करने की कोई आवश्यकता नहीं है।

हालांकि, यदि आप चाहते हैं कि समान कोड काम सी ++ प्लेटफॉर्म पर पूरी तरह से संगत हो, जो निहित रूपांतरण का समर्थन नहीं करता है, तो आपको टाइपकास्टिंग करने की आवश्यकता है, इसलिए यह सब प्रयोज्य पर निर्भर करता है।


9
  1. जैसा कि अन्य कहा गया है, यह C के लिए नहीं, बल्कि C ++ के लिए आवश्यक है।

  2. कलाकारों को शामिल करने से सी प्रोग्राम या फ़ंक्शन को C ++ के रूप में संकलित करने की अनुमति मिल सकती है।

  3. सी में यह अनावश्यक है, क्योंकि शून्य * स्वचालित रूप से और सुरक्षित रूप से किसी अन्य पॉइंटर प्रकार को बढ़ावा दिया जाता है।

  4. लेकिन अगर आप तब डालते हैं, तो यह एक त्रुटि छिपा सकता है यदि आप stdlib.h को शामिल करना भूल गए । इससे क्रैश (या इससे भी बदतर, कोड के कुछ पूरी तरह से अलग हिस्से में बाद में तब तक दुर्घटना का कारण नहीं बन सकता है)।

    क्योंकि stdlib.h में मॉलोक का प्रोटोटाइप पाया जाता है। मॉलोक के लिए एक प्रोटोटाइप की अनुपस्थिति में, मानक की आवश्यकता है कि सी कंपाइलर मानता है कि मॉलोक एक इंट रिटर्न देता है। यदि कोई डाली नहीं है, तो यह पूर्णांक सूचक को सौंपा जाने पर एक चेतावनी जारी की जाती है; हालांकि, कलाकारों के साथ, इस चेतावनी का उत्पादन नहीं किया जाता है, बग को छिपाते हुए।


7

मॉलोक की कास्टिंग सी में अनावश्यक है लेकिन सी ++ में अनिवार्य है।

सी के कारण कास्टिंग अनावश्यक है:

  • void * सी के मामले में किसी भी अन्य पॉइंटर प्रकार के लिए स्वचालित रूप से और सुरक्षित रूप से पदोन्नत किया गया है।
  • यदि आप शामिल करना भूल गए तो यह एक त्रुटि छिपा सकता है <stdlib.h>। इससे दुर्घटना हो सकती है।
  • यदि पॉइंटर्स और पूर्णांक अलग-अलग आकार के हैं, तो आप कास्टिंग द्वारा चेतावनी छिपा रहे हैं और आपके लौटे पते के बिट्स खो सकते हैं।
  • यदि पॉइंटर के प्रकार को इसकी घोषणा में बदल दिया जाता है, तो किसी को सभी लाइनों को बदलने की आवश्यकता भी हो सकती है जहां mallocकॉल किया जाता है और डाली जाती है।

दूसरी ओर, कास्टिंग आपके प्रोग्राम की पोर्टेबिलिटी बढ़ा सकती है। यानी, यह C प्रोग्राम या फ़ंक्शन को C ++ के रूप में संकलित करने की अनुमति देता है।


0

मेरे लिए, घर ले जाओ और निष्कर्ष यह है कि mallocसी में कास्टिंग पूरी तरह से आवश्यक नहीं है, लेकिन अगर आप फिर भी डालते हैं, तो यह प्रभावित नहीं करेगा mallocक्योंकि mallocअभी भी आपके द्वारा अनुरोधित आशीर्वाद स्थान को आवंटित करेगा। एक और घर लेना कारण है या एक कारण है कि लोग कास्टिंग करते हैं और यह उन्हें सी या सी ++ में एक ही कार्यक्रम संकलित करने में सक्षम बनाता है।

अन्य कारण हो सकते हैं लेकिन अन्य कारण, लगभग निश्चित रूप से, आपको जल्द या बाद में गंभीर संकट में डाल देंगे।


0

आप कर सकते हैं, लेकिन आपको सी में डालने की जरूरत नहीं है। यदि आपको वह कोड सी + + के रूप में संकलित करना है।

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