2012-06-06 11 views
14

कार्य करने के लिए करने के लिए स्थिरांक कीवर्ड को जोड़ने का है वहाँ किसी भी तरह से है कि मैं एक सरणी समारोह के लिए एक पैरामीटर के रूप में पारित करने के लिए const कीवर्ड जोड़ सकते हैं:एक सरणी एक पैरामीटर के रूप में पारित

void foo(char arr_arg[]) 

अगर मैं constchar से पहले जगह (void foo(const char arr_arg[])) या char (void foo(char const arr_arg[])) के बाद, इसका मतलब char से अधिक होगा जो arr_arg नहीं है।

मुझे लगता है कि हुड के नीचे कार्य करने के लिए एक पैरामीटर के रूप में भेजा एक सरणी सूचक के रूप में प्रस्तुत किया जाता है तो बस read है, तो void foo(char arr_arg[])void foo(char* ptr_arg) के समान है। इसे ध्यान में रखते हुए, मैं इस कार्य को void foo(char * const ptr_arg) के रूप में फिर से लिख सकता हूं क्योंकि यह वही होना चाहिए जो मैं प्राप्त करना चाहता हूं।

लेकिन मैं अगर वहाँ इस घोषणा void foo(char arr_arg[]) में const कीवर्ड जोड़ने के लिए यह रूप में एक ही होने के लिए एक तरीका है जानना चाहता हूँ void foo(char * const ptr_arg) (और void foo(char const * ptr_arg) या void foo(const char * ptr_arg) नहीं)?

मैं सिर्फ यह समझना चाहता हूं कि arr_arg को सरणी नोटेशन [] के साथ स्थिर बनाने के लिए कोई वाक्यविन्यास है या नहीं।

+4

कोई विशेष कारण आप 'शून्य foo (चार * स्थिरांक ptr_arg)' ऐसा करने के लिए नहीं करना चाहती है? यह हर जगह बिल्कुल वही वाक्यविन्यास है। आप अभी भी ptr_arg [0] कर सकते हैं जैसे कि इसे सरणी के रूप में घोषित किया गया हो। –

+0

@ हंस मैं सिर्फ यह समझना चाहता हूं कि यह सरणी नोटेशन के साथ इसे करने के लिए वाक्य रचनात्मक रूप से संभव है या नहीं। [] '। कोई विशिष्ट कारण नहीं है। बस यह स्पष्ट करना चाहते हैं कि यह संभव है या नहीं (केवल भविष्य में जानना और समय पर बर्बाद न करें अगर यह संभव है या बार-बार नहीं)। – ovgolovin

+0

मुझे नहीं लगता कि पॉइंटर को स्वयं को कॉन्स्ट के रूप में घोषित करने की आवश्यकता है क्योंकि इसे वैसे भी मूल्य से पारित किया जाएगा। केवल तभी जब आप स्पष्ट रूप से फ़ंक्शन परिभाषा के अंदर असाइन करने (स्टैक पर पॉइंटर की प्रति) से रक्षा करना चाहते हैं। –

उत्तर

16

सी में आप[] के बीच constडाल करने के लिए है, लेकिन अजीब है कि एक अप्रस्तुत व्यक्ति

void foo(char arr_arg[const]); 

यह वह जगह है 'नई' C99-specific syntax को लग सकता है। सी 8 9/9 0 या सी ++ में "सरणी" वाक्यविन्यास के साथ ऐसा करने का कोई तरीका नहीं है, इसलिए आपको डेविड के उत्तर में सुझाए गए समकक्ष "पॉइंटर" वाक्यविन्यास पर स्विच करना होगा।

+0

धन्यवाद जैसे पॉइंटर का संदर्भ! मैं कुछ मिनटों में जवाब स्वीकार करूंगा (जब एसओ मुझे ऐसा करने देगा)। क्या आप सी 99, सी 8 9/9 0 के बारे में कुछ शब्द लिख सकते हैं (उन लोगों के लिए जो इस जवाब को पढ़ रहे होंगे, उनमें से कुछ के लिए Google को खोजना नहीं है कि वे क्या हैं)? – ovgolovin

+0

@ovgolovin 6.7.5.3p7 – ouah

+1

@ovgolovin में सी 99 में जोड़ा गया: ध्यान दें कि तर्क अभी भी एक सरणी नहीं है, लेकिन एक * सूचक * है, और वह सूचक प्रतिलिपि बनाई गई है, जिसका अर्थ है कि मूल सूचक (और सरणी) को बदला नहीं जा सकता समारोह के अंदर। यदि आप वास्तविक सरणी (गतिशील रूप से आवंटित स्मृति के बजाए) के बारे में बात कर रहे हैं, तो सरणी अपरिवर्तनीय है (सामग्री को बदला जा सकता है, लेकिन एक कंटेनर के रूप में सरणी नहीं कर सकती है) इसलिए इसे 'const' –

8

पहली बात यह है कि अपने विशेष हस्ताक्षर में, तर्क एक सूचक में संकलक द्वारा तब्दील हो जाता है है, तो क्या आपके पास है:

void foo(char * arg); 

अब, वहाँ दो संस्थाओं है कि में स्थिरांक की जा सकती हैं वह हस्ताक्षर: सूचक और बिंदु प्रकार। नुकीली प्रकार बनाने के लिए दो अलग-अलग अभी तक बराबर तरीके [*] में स्थिरांक बनाया जा सकता है:

void foo(const char * arg); 
void foo(char const * arg); 

सूचक वाक्य रचना के साथ स्थिरांक बनाया जा सकता है:

void foo(char * const arg); 

लेकिन ध्यान दें कि एक समारोह में हस्ताक्षर , उसी तरह char arg[] को पॉइंटर char *arg में बदल दिया गया है, शीर्ष स्तर क्वालीफायर को त्याग दिया गया है। तो घोषणा की दृष्टि से, इन दोनों बराबर हैं:

void foo(char * const arg); 
void foo(char *  arg); 

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

[*] मैं char const * प्रारूप पसंद करते हैं, के रूप में यह प्रकार पढ़ने का एक सुसंगत तरीका प्रदान करता है: दाएं से बाएं इसे पढ़ता है: एक स्थिरांक चार लिए एक गैर स्थिरांक सूचक। इसके अतिरिक्त टाइपिफ़-एड प्रकारों (अभिव्यक्ति में प्रत्यक्ष प्रतिस्थापन करके) के कारणों के कारण यह आसान है। typedef char* char_p;, const char_p और char_p constchar * const के बराबर हैं और const char * से अलग हैं। दाईं ओर const का उपयोग करके आप केवल टाइप किए गए टाइप को अंधा कर सकते हैं और कारण के बिना प्रकार को पढ़ सकते हैं।

2

हाँ, सी में यह संभव है C99 के बाद से:

void foo(char *const ptr_arg); 

void foo(char ptr_arg[const]); 

मान्य सिंटैक्स और बराबर है करने के लिए और अधिक आम तौर [] किसी भी प्रकार के क्वालीफायर, static और एक पूर्णांक अभिव्यक्ति हो सकती है। लेकिन

वैकल्पिक प्रकार क्वालिफायर और कीवर्ड static एक सरणी प्रकार के साथ एक समारोह पैरामीटर की घोषणा में केवल दिखाई देगा, और उसके बाद ही सबसे बाहरी सरणी प्रकार व्युत्पत्ति में ।

जो कि सूचक घोषणा के बराबर आयाम के लिए है।

+0

@MooingDuck , मैंने कभी नहीं कहा कि यह सी ++ के लिए है, अब मैं सी पर जोर देता हूं और ओपी अभी भी दावा करता है कि वह सी में भी रूचि रखता है, इसलिए इस उत्तर को कोई नुकसान नहीं होता है। –

+0

गलतफहमी के लिए खेद है। मैंने सोचा कि यह सी और सी ++ में समान है। लेकिन फिर जब मुझसे पूछा गया, तो मैंने केवल सी ++ छोड़ा (जो संकलक मैं अब उपयोग कर रहा हूं)। लेकिन वास्तव में सी के बारे में जानना बहुत दिलचस्प है। अब मुझे पता है कि यह असंभव था और केवल सी 99 के आने के साथ ही संभव हो गया। – ovgolovin

0

सी ++ के लिए, टेम्पलेट का उपयोग करके डक का जवाब म्यूइंग सबसे सीधे आगे है।

आप सी कोड है कि एक सी इंटरफेस सी ++ में लागू बुला रहा है, तो आप एक सूचक बहस में बजाय तर्क परिवर्तित करने, और बनाने के साथ फंस रहे हैं const

कि आप सी उपयोग करने के बजाय Boost's array उपयोग किया है तो है, तो सरणियों सीधे, तो आप उस const बनाने के लिए सक्षम, होगा, हालांकि यह भी एक टेम्पलेट समारोह होगा:

template <unsigned N> 
void foo (Boost::array<char, N> const & arg) {} 

Boost::array का लाभ यह है कि आप बंद एक सरणी के एक हल्के वजन आवंटन करने की क्षमता देता है ढेर, लेकिन पूरा करने में सक्षम हो वाई एसटीएल एल्गोरिदम का उपयोग करें जो कंटेनर में लक्षणों पर निर्भर करता है।

+0

उस दूसरे के साथ सावधान, क्योंकि यह पृष्ठ पर और अन्य सभी उत्तरों के लिए पूछे जाने से अलग है। जिस डेटा पर सरणी इंगित करती है वह स्थानीय है, और _also_ const। –

+0

@MooingDuck: मैंने C++ में सी स्टाइल सरणी पर बूस्ट :: सरणी का उपयोग करने और आपके पोस्ट पर +1 का उपयोग करने के लाभ को इंगित करने के लिए उत्तर संशोधित किया। – jxh

2

सी ++ में कई तरीके हैं, लेकिन कोई भी काफी जो आप उम्मीद कर रहे हैं।

//typedef has a very clear intent 
typedef char* array; 
void f0(const array a) {} 

//switch to pointers to sidestep the problem 
void f1(char* const a) {} 

//references are inherently const 
//can't take pointers, but guarantees the size, sometimes nice 
//this version obviously doesn't work in C 
template<int n> 
void f2(char (&a)[n]) {} 

http://ideone.com/4LvYT

+0

'शून्य एफ 0 (कॉन्स एरे ए) नहीं है '' void f0 (const char * a)' जैसा है (जो 'char' स्थिर बनाता है, न कि 'a')? – ovgolovin

+0

नहीं, 'सरणी' एक पूर्ण प्रकार है, और 'const array' टाइप 'array' प्रकार का 'const' चर बनाता है। फ़ंक्शन पॉइंटर्स के आस-पास गुजरते समय यह _very_ सामान्य चाल है, अन्यथा सिंटैक्स अनावश्यक है। –

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