2012-05-18 60 views
15

मैं एक ऐसा फ़ंक्शन लिखना चाहता हूं जिसमें va_list का रिटर्न प्रकार हो।सी में va_list सुरक्षित लौट रहा है?

उदाहरण: va_list MyFunc(va_list args);

यह सुरक्षित और पोर्टेबल है?

+4

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

+0

यह बिल्कुल मेरा इरादा है। क्या आप इंगित कर सकते हैं कि मानक में कहां अनुमति है? –

+2

मेरी राय में, 'va_list' एक बुरा विचार है। आमतौर पर बेहतर समाधान होते हैं जो अधिक सुरक्षित होते हैं। तो मुझे एक कठिन विचार होगा और समारोह के डिजाइन और कार्यान्वयन के लिए एक बेहतर समाधान प्राप्त होगा। –

उत्तर

6

va_list (लेकिन इसकी गारंटी नहीं है) एक सरणी प्रकार हो, ताकि आप इसे मूल्य से पास या वापस नहीं कर सकें। कोड जो ऐसा लगता है, हो सकता है कि वह पहले तत्व में पॉइंटर को पास/वापस कर रहा हो, ताकि आप कैली में पैरामीटर का उपयोग कर सकें लेकिन आप मूल पर अभिनय कर सकते हैं।

औपचारिक रूप से आप शायद कह सकते हैं कि va_list एक इकाई प्रकार है, न कि मूल्य प्रकार। आप इसे va_copy के साथ कॉपी करते हैं, असाइनमेंट के साथ या फ़ंक्शन पैरामीटर/रिटर्न के माध्यम से नहीं।

1

जबकि आप निश्चित रूप से return ऐसे मूल्य का उपयोग कर सकते हैं, मुझे यकीन नहीं है कि वापसी मूल्य का उपयोग उपयोगी तरीके से किया जा सकता है या नहीं।

va_list रों की हैंडलिंग के रूप में विशेष व्यवहार (va_end()va_start() और va_copy() के बाद) की आवश्यकता है, और va_start/copy और va_end मैक्रो भी { } को रोकने के लिए इस युग्मन को लागू करने के लिए अनुमति दी जाती है, तो आप दूसरे के बिना एक फोन नहीं कर सकते हैं की आवश्यकता है।

+3

'va_copy' का उपयोग * * * * va_list' ऑब्जेक्ट बनाने के लिए किया जाता है जिसे मूल रूप से स्वतंत्र रूप से पढ़ा जा सकता है। चूंकि यह मामला यहां नहीं है, तो मैं कहूंगा कि 'va_list' ऑब्जेक्ट को पास करना और वापस करना ठीक है। साथ ही, मानक का उल्लेख नहीं है कि 'va_start() 'और' va_end() 'एक ही दायरे में होना चाहिए, इसलिए मुझे नहीं लगता कि उन्हें' {': es। – Lindydancer

+2

@ लिंडिडांसर ओह, इसके बारे में नहीं पता था। [यहां] (http://linux.die.net/man/3/va_start) मैंने पढ़ा "va_start() का प्रत्येक आमंत्रण उसी कार्य में va_end() के संबंधित आमंत्रण से मेल खाना चाहिए" और "प्रत्येक आमंत्रण va_copy() को उसी फ़ंक्शन में va_end() के संबंधित आमंत्रण से मेल खाना चाहिए। ", इसलिए मैंने सोचा कि यह मानक से cones ... – glglgl

+0

@glglgl:" एक ही फ़ंक्शन में "का अर्थ यह नहीं है" एक ही दायरा ", इसलिए यह नहीं दर्शाता है कि मैक्रोज़ बेजोड़ ब्रेसिज़ का उपयोग कर सकते हैं। लेकिन यह 'va_copy' को 'alloca' जैसी चाल का उपयोग करने की अनुमति देता है, क्योंकि नई सूची फ़ंक्शन रिटर्न से परे नहीं रहती है। –

1

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

va_list प्रकार लौटने से वास्तव में सूची की सामग्री को कॉलर पर कॉपी करने की संभावना नहीं है। यद्यपि यह सी का वैध कार्यान्वयन होगा, यदि मानक को ऐसा करने की आवश्यकता है, तो यह विनिर्देशन में एक दोष होगा।

+0

कारण 'va_end' मैक्रो मौजूद है क्योंकि' va_list' केवल स्टैक पर कुछ के लिए एक सूचक नहीं है। अन्यथा, 'va_end' हमेशा एक नो-ऑप होगा। वहां कार्यान्वयन मौजूद हैं जहां ढेर पर 'va_list' ऑब्जेक्ट आवंटित किए जाते हैं। –

+0

@DietrichEpp अच्छी जानकारी, मैंने सोचा था कि 'va_end' के पास रजिस्टर विंडो या पुराने कार्यान्वयन के साथ कुछ करना था जो एक समय में केवल एक इटरेटर को अनुमति देता था। मेरे जवाब को समायोजित किया, लेकिन यह सिर्फ सापेक्ष जोर का मामला है ... अधिकांश आर्किटेक्चर varargs के लिए ढेर का उपयोग नहीं करते हैं। – Potatoswatter

0

किसी अन्य फ़ंक्शन पर पॉइंटर पास करना से काफी अलग है, हालांकि उस पॉइंटर को वापस कर रहा है। vararg फ़ंक्शन रिटर्न के दौरान कई/अधिक कार्यान्वयन वास्तविक चर तर्कों को संग्रहीत करते हैं जो नष्ट हो जाते हैं। (यानी पर एक va_list या पॉइंटर लौटाकर, आपको स्थानीय चर के पॉइंटर्स के साथ छोड़ देगा जो नष्ट हो गया है)। - ओपन स्कूल

मेरे मामले में अच्छी तरह से

मैं चेतावनी के लिए va_list लौटने होगी वापस लेकिन धन्यवाद - Hayri Uğur Koltuk

आप समारोह MyFunc(va_list *args) करने के लिए एक va_list के लिए सूचक पारित, तो आप की जरूरत नहीं है संशोधित (va_arg(*args, type) द्वारा) तर्क सूची को वापस करने के लिए, क्योंकि MyFunc मूल सूची को संशोधित करता है।

+0

मुझे नहीं लगता कि यह निर्दिष्ट है कि 'MyFunc' मूल सूची को संशोधित करता है या नहीं। मुझे निश्चित रूप से कार्यान्वयन का सामना करना पड़ा है जो दोनों तरीकों से काम करता है। – supercat

+0

@supercat - यदि किसी ऑब्जेक्ट के लिए कोई पॉइंटर किसी फ़ंक्शन पर पास हो जाता है, और फ़ंक्शन पॉइंट-टू ऑब्जेक्ट को संशोधित करता है, तो यह निहित है कि मूल ऑब्जेक्ट संशोधित है। – Armali

+0

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