दिलचस्प पोस्ट
मूल / सिर कैसे सेट हो जाता है? अजगर में विशिष्ट लंबाई के साथ यादृच्छिक संख्या कैसे उत्पन्न करें पायथन – कई मैचों को खोजने और उन्हें प्रिंट करने के लिए regex का उपयोग करना क्या आप कभी भी सुरक्षित सदस्य चर का उपयोग करना चाहिए? सभी jquery घटनाओं $ (दस्तावेज़) के लिए बाध्य होना चाहिए? एंड्रॉइड: बैक स्टैक को साफ़ करें स्क्रॉल दृश्य स्क्रॉल पदों को सिंक्रनाइज़ करें – एंड्रॉइड .NET में एक ऑब्जेक्ट को serializing करते समय सभी xsi और xsd नामस्थानों को छोड़कर? मैं SearchView प्रोग्राम को कैसे खोलूं? मृदुरीय रिपॉजिटरी के साथ गिट इंटरऑपरेबिलिटी धाराप्रवाह Nhibernate से XML मैपिंग उत्पन्न करें Laravel 4 यूआरएल से जनता को हटाने WWDC 2010 नमूना कोड एक HTTP POST कितना सुरक्षित है? -पैथथ और -एल के बीच क्या अंतर है?

एक सरणी नाम या फ़ंक्शन का नाम कब 'सूचक' में किया जाता है? (सी में)

1) गलत धारणा :

2) मैंने इस सवाल से इसे उठाया।

  • ज्यादातर मामलों में सरणी नामों को पॉइंटर्स में बदल दिया जाता है

क्या कोई भी WHEN का विस्तृत विवरण दे सकता है कि कंपाइलर एक सरणी नाम को एक संकेतक में कनवर्ट करने का निर्णय करता है, और क्यों ?

पुनश्च: कृपया कार्यों के साथ ही समझाएं। इसके अलावा, इस लिंक में, एक उदाहरण दिया गया था कि यह कहा जाता है कि फ़ंक्शन के लिए int square(int,int) , किसी भी square , &square , *square , **square एक ही समारोह सूचक को संदर्भित करता है क्या तुम समझा सकते हो?

संपादित करें: कोड स्निपेट

 int fruits[10]; printf("Address IN constant pointer is %p\n", fruits); printf("Address OF constant pointer is %p\n", &fruits); 

आउटपुट:

 Address IN constant pointer is 0xbff99ca8 Address OF constant pointer is 0xbff99ca8 

Solutions Collecting From Web of "एक सरणी नाम या फ़ंक्शन का नाम कब 'सूचक' में किया जाता है? (सी में)"

सरणी प्रकार की अभिव्यक्ति पर सरलीकृत ऑब्जेक्ट के पहले तत्व को संकेतक के रूप में परिवर्तित किया जाता है, जब तक कि यह नहीं है:

  • यूनरी & ऑपरेटर का संचालन;
  • sizeof संचालन; या
  • सरणी ऑब्जेक्ट को इनिशियलाइज़ करने के लिए उपयोग किए जाने वाले प्रारंभकर्ता में एक स्ट्रिंग शब्दशः

तीसरे मामले के एक उदाहरण हैं:

 char arr[6] = "hello"; 

"hello" एक सरणी अभिव्यक्ति है, प्रकार char[6] (5 प्लस 1 को '\0' टर्मिनेटर के लिए)। यह किसी पते पर परिवर्तित नहीं है; "hello" का पूरा 6-बाइट मान सरणी ऑब्जेक्ट arr में कॉपी किया जाता है

दूसरी ओर, इसमें:

 char *ptr = "hello"; 

सरणी अभिव्यक्ति "hello" 'h' पर एक संकेतक के लिए "decays", और उस पॉइंटर वैल्यू का उपयोग सूचक ऑब्जेक्ट ptr को प्रारंभ करने के लिए किया जाता है (यह वास्तव में const char *ptr होना चाहिए, लेकिन यह एक तरफ मुद्दा है।)

फंक्शन प्रकार की अभिव्यक्ति (जैसे कि फ़ंक्शन नाम) को संकेतक को फ़ंक्शन में तब तक रूपांतरित कर दिया जाता है जब तक कि यह नहीं है:

  • यूनरी & ऑपरेटर का संचालन; या
  • sizeof function_name ( sizeof function_name अवैध है, एक सूचक का आकार नहीं)

बस।

दोनों मामलों में, कोई सूचक ऑब्जेक्ट बनाया नहीं है अभिव्यक्ति को एक सूचक मूल्य ("decays" में परिवर्तित किया जाता है), जिसे एक पता भी कहा जाता है।

ध्यान दें कि दोनों सरणी अनुक्रमण ऑपरेटर [] और फ़ंक्शन कॉल "ऑपरेटर" () को एक संकेतक की आवश्यकता होती है। एक सामान्य फ़ंक्शन कॉल जैसे func(42) , फ़ंक्शन का नाम "डिकेशन्स" को पॉइंटर-टू-फ़ंक्शन के लिए, जो कि फिर कॉल में उपयोग किया जाता है। (यह रूपांतरण वास्तव में उत्पन्न कोड में नहीं किया जाना चाहिए, जब तक फ़ंक्शन कॉल सही काम करता है।)

कार्यों के लिए नियम कुछ अजीब परिणाम हैं। अभिव्यक्ति func , अधिकतर संदर्भों में फ़ंक्शन फ़ंक्शन में एक पॉइंटर में कनवर्ट किया जाता है। &func , func को एक सूचक में परिवर्तित नहीं किया जाता है, लेकिन फ़ंक्शन के पते को उत्पन्न करता है, अर्थात, एक सूचक मूल्य। *func , func को सूचक पर रूपांतरित कर दिया जाता है, फिर * फ़ंक्शन को उपज देने के लिए इसे वरीयता देता है, जो तब (अधिकांश संदर्भों में) एक सूचक में परिवर्तित होता है। ****func , यह बार-बार होता है

(सी 11 मानक के एक ड्राफ्ट का कहना है कि एरे के लिए एक और अपवाद है, अर्थात् जब सरणी नए _Alignof ऑपरेटर का संचालन है, तो अंतिम प्रकाशित C11 मानक में सही मसौदा में यह एक त्रुटि है; _Alignof को केवल लागू किया जा सकता है एक अभिव्यक्ति के लिए नहीं, एक कोष्ठक प्रकार का नाम।)

एक सरणी का पता और इसके पहले सदस्य का पता:

 int arr[10]; &arr; /* address of entire array */ &arr[0]; /* address of first element */ 

एक ही स्मृति पते हैं, लेकिन वे विभिन्न प्रकार के होते हैं। पूर्व संपूर्ण ऑरेजेक्ट ऑब्जेक्ट का पता होता है, और यह टाइप int(*)[10] (10 int की सरणी के लिए पॉइंटर) है; उत्तरार्द्ध प्रकार int* दो प्रकार संगत नहीं हैं (आप कानूनी रूप से एक int(*)[10] ऑब्जेक्ट के लिए कानूनी तौर पर एक int* वैल्यू नहीं दे सकते, उदाहरण के लिए), और पॉइंटर अंकगणित उन पर अलग ढंग से व्यवहार करता है।

एक अलग नियम है जो कहता है कि सरणी या फ़ंक्शन प्रकार का एक घोषित फ़ंक्शन पैरामीटर को संकलक समय (कनवर्ट नहीं) पर पॉइंटर पैरामीटर में समायोजित किया जाता है उदाहरण के लिए:

 void func(int arr[]); 

बिल्कुल के बराबर है

 void func(int *arr); 

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

Comp.lang.c अकसर किये गए सवाल का खंड 6 विवरण समझाते हुए एक उत्कृष्ट काम करता है।

इसके लिए निश्चित स्रोत आईएसओ सी मानक है। N1570 (1.6 एमबी पीडीएफ) 2011 मानक का नवीनतम मसौदा है; इन रूपांतरणों को खंड 6.3.2.1, पैराग्राफ 3 (एरे) और 4 (फ़ंक्शन) में निर्दिष्ट किया गया है। यह ड्राफ्ट _Alignof का गलत संदर्भ है, जो वास्तव में लागू नहीं होता है

संयोग से, आपके उदाहरण में printf कॉल कड़ाई से गलत हैं:

 int fruits[10]; printf("Address IN constant pointer is %p\n",fruits); printf("Address OF constant pointer is %p\n",&fruits); 

%p प्रारूप में टाइप void* तर्क की आवश्यकता है यदि प्रकार के int* और int(*)[10] संकेतक void* रूप में समान प्रतिनिधित्व करते हैं और उसी तरह तर्क के रूप में पारित होते हैं, जैसा कि अधिकांश कार्यान्वयन के मामले में होता है, यह काम करने की संभावना है, लेकिन इसकी गारंटी नहीं है। आपको पॉइंटर्स को स्पष्ट रूप से void* बदलना चाहिए:

 int fruits[10]; printf("Address IN constant pointer is %p\n", (void*)fruits); printf("Address OF constant pointer is %p\n", (void*)&fruits); 

तो यह ऐसा क्यों किया जाता है? समस्या यह है कि arrays सी में दूसरी श्रेणी के नागरिकों में हैं। आप फंक्शन कॉल में एक तर्क के रूप में मूल्य से एक सरणी नहीं दे सकते, और आप इसे फ़ंक्शन परिणाम के रूप में नहीं लौटा सकते। सरणियों के लिए उपयोगी होने के लिए, आपको अलग-अलग लंबाई के सरणियों पर काम करना चाहिए। char[1] लिए अलग-अलग strlen फ़ंक्शंस, char[1] लिए char[2] , char[3] , और बहुत आगे (जो सभी अलग-अलग हैं) असंभव रूप से बोझल होंगे। इसके बजाय पॉइंटर अंकगणित के साथ उन तत्वों को पार करने का एक मार्ग प्रदान करने के साथ, इसके बजाय सरणियों को उनके तत्वों के लिए पॉइंटर्स के माध्यम से पहुंचाया जाता है।

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

अन्य भाषाएं प्रथम श्रेणी के प्रकार के रूप में एरेज़ से निपटने में सक्षम हैं लेकिन ऐसा करने से अतिरिक्त सुविधाओं की आवश्यकता होती है जो "सी की भावना में" नहीं होती, जो अपेक्षाकृत निम्न-स्तरीय भाषा रही है

मैं इस तरह से कार्यों के इलाज के लिए तर्क के बारे में निश्चित नहीं हूँ यह सच है कि फ़ंक्शन प्रकार के कोई मूल्य नहीं हैं , लेकिन फ़ंक्शन कॉल में उपसर्ग के रूप में एक फ़ंक्शन (एक पॉइंटर-टू-फ़ंक्शन के बजाय) की आवश्यकता हो सकती थी, जिसके लिए एक अप्रत्यक्ष कॉल के लिए एक स्पष्ट * ऑपरेटर की आवश्यकता होती है: (*funcptr)(arg) * को छोड़ने में सक्षम होना एक सुविधा है, लेकिन एक जबरदस्त एक नहीं है यह संभवतः एरे के इलाज के साथ ऐतिहासिक जड़ता और स्थिरता का एक संयोजन है।

आपके प्रश्न के पहले भाग में लिंक किए गए पृष्ठ में दिया गया विवरण निश्चित रूप से पूरी तरह से गलत है वहां कोई सूचक नहीं है, स्थिर या नहीं @ किथथॉम्पसन के जवाब में आप सरणी / फ़ंक्शन व्यवहार का संपूर्ण विवरण पा सकते हैं।

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

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

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

संक्षिप्त जवाब हाँ है … कभी-कभी के अलावा आम तौर पर एक सरणी के घोषित होने के बाद, हर बार इसका नाम प्रयोग किया जाता है, इसे सरणी ऑब्जेक्ट के पहले एंट में पॉइंटर में कनवर्ट किया जाता है। हालांकि कुछ मामलों में ऐसा नहीं होता है। इन मामलों में जहां ऐसा नहीं होता है, यहां @ किथथॉम्पसन के उत्तर में पाया जा सकता है

इसी तरह आपके सरणी के लिए, फ़ंक्शन प्रकार को भी सूचक मूल्य में परिवर्तित किया जायेगा … कभी-कभी इसके अलावा जिन मामलों में यह फिर से घटित नहीं होता है, उन्हें फिर से @ किथथॉम्पसन के उत्तर में पाया जा सकता है। यहां

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

आपको याद रखना जरूरी नहीं है कि, ओह, यह sizeof '' को छोड़कर '' को छोड़कर, और 'आदि' में परिवर्तित हो जाता है। आपको अभिव्यक्ति के संदर्भ के बारे में अभी सोचना होगा

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

या, यदि आप dereference ऑपरेटर * , या अंकगणितीय ऑपरेटरों + - , या सबस्क्रिप्ट ऑपरेटर, [] साथ एक सरणी अभिव्यक्ति का उपयोग करते हैं; ये ऑपरेटर सभी पॉइंटर्स पर काम करते हैं, फिर से, संकलक यह देखता है, और रूपांतरण लागू करता है।

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

जब आप इसे sizeof साथ उपयोग करते हैं, और & , ये संदर्भ सरणी के लिए स्वाभाविक रूप से समझते हैं, इसलिए संकलक रूपांतरण लागू करने के लिए परेशान नहीं करता है। एकमात्र कारण है कि इन्हें सरणी-टू-पॉइंटर रूपांतरण के "अपवाद" के रूप में देखा जाता है, केवल यह है कि, सी में अन्य सभी अभिव्यक्ति संदर्भ (जैसा कि ऊपर दिए गए उदाहरणों में आप देख सकते हैं) सर प्रकारों के लिए नहीं समझते हैं (सरणी प्रकार सी में इतना अपंग हैं), और ये केवल कुछ ही "बाएं" हैं