क्या करता है ((शून्य (*) ()) buf) (); क्या मतलब है?


59

मैं picoCTF पर एक द्विआधारी शोषण चुनौती का समाधान कर रहा हूं और इस कोड के टुकड़े पर आया हूं:

((void (*)())buf)();

जहां bufएक चरित्र सरणी है।

मैंने चुनौती को हल कर दिया, लेकिन यह समझ नहीं पाया कि वास्तव में यह क्या कर रहा है। मैंने इस धागे को देखा लेकिन मैं इसे नहीं बना पाया।

क्या ((void (*)())buf)();मतलब है?


14
क्या ((void (*)())buf)();मतलब है? इसका मतलब है कि लेखक समझ नहीं पाता है typedeftypedef void (*voidFuncPtrType)();यह कोड स्पष्ट कर देगा।
एंड्रयू हेनले

33
@AndrewHenle सीटीएफ चुनौतियों को डिजाइन करने में, स्पष्टता वास्तव में सर्वोच्च लक्ष्य नहीं है, और कुछ बाधाओं को चुनौती के हिस्से के रूप में भी उम्मीद की जा सकती है। अधिक संभावना नहीं है, लेखक को पता था कि यह चीजों को करने का सबसे पठनीय तरीका नहीं है।
ManfP

2
इसका मतलब है कि आपके कार्यक्रम में यूबी है।
आर .. गिटहब स्टॉप हेल्पिंग ICE

4
इसका मतलब है कि सी "सर्पिल" प्रकार की घोषणा का तरीका बहुत जटिल है। लगभग हर दूसरी वैधानिक रूप से टाइप की जाने वाली भाषा है जो C से सीधे नहीं उतरती है, इसके बजाय बाएं से दाएं नियमों का उपयोग करती है।
मेसन व्हीलर

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

जवाबों:


129

void (*)() एक प्रकार है, टाइप किया जा रहा है "सूचक कार्य करने के लिए जो अनिश्चित तर्क लेता है और कोई मूल्य नहीं देता है"।

(void (*)()) उपरोक्त प्रकार का एक प्रकार है।

(void (*)())bufbufउपरोक्त प्रकार के लिए डाले ।

((void (*)())buf)() फ़ंक्शन को कॉल करता है (कोई तर्क नहीं दे रहा है)।

संक्षेप में: यह कंपाइलर bufको किसी फ़ंक्शन के लिए पॉइंटर के रूप में व्यवहार करने और उस फ़ंक्शन को कॉल करने के लिए कहता है।


15
मैं cdeclउपयोगिता (या वेबसाइट ) को अंग्रेजी में अधिक जटिल सी अभिव्यक्तियों के अनुवाद के लिए मददगार पाता हूं ।
बटा

3
@ बटा cdecl यहाँ उपयोगी नहीं है क्योंकि वाक्यविन्यास एक घोषणा नहीं है। यह एक फ़ंक्शन है जो पहले घोषित प्रतीक पर एक कलाकार के माध्यम से है
बोलोव

3
@bolov - पूरे बयान पर, नहीं, लेकिन यह इसके सबसे जटिल हिस्से की व्याख्या करता है। वहां से, बाकी को डिकोड करना काफी सीधा है।
BTA

5
@ एवीडी अगर कहीं भी है bufया copyनिष्पादन योग्य पते पर है और कोड स्वयं स्थिति-स्वतंत्र है, तो यह काम करेगा। यह बेशक गैर-पोर्टेबल है जितना इसे मिलता है, लेकिन यह कई नंगे-धातु वातावरणों के साथ-साथ पुराने x86 OSes में भी काम करना चाहिए जो स्टैक और हीप पर नो-एक्ज़ीक्यूट (NX) बिट सेट नहीं करते हैं।
wrtlprnft

4
@ एवीडी: यह जरूरी दुर्घटना नहीं होगी। जब तक डेटा क्षेत्र को निष्पादन (जो आर्किटेक्चर और रन-टाइम वातावरण पर निर्भर करता है) के खिलाफ सुरक्षित है, तो आप इस ट्रिक का उपयोग रन-टाइम में एक सरणी में संकलन करने और मक्खी पर कॉल करने के लिए कर सकते हैं। मैंने ट्यूरिंग मशीन के विकास में एक असफल प्रयोग के लिए ट्यूरिंग मशीनों को संकलित करने के लिए डीईसी वैक्स पर 35 साल पहले इस चाल का उपयोग किया था।
टोनीके

11

पॉइंटर bufको पॉइंटर में कनवर्ट किया जाता है ताकि शून्य मानदंड की अनिर्दिष्ट संख्या हो और फिर डिफरेंस्ड (यानी फंक्शन कहा जाता है)।


9

यह एक टाइपकास्ट है, इसके बाद एक फंक्शन कॉल आता है। सबसे पहले, bufपॉइंटर को एक फ़ंक्शन पर लौटाया जाता है जो वापस लौटता है void। कोष्ठक की अंतिम जोड़ी का मतलब है कि फ़ंक्शन तब कहा जाता है।


7

यह बिना किसी तर्क के एक फ़ंक्शन के पॉइंटर पॉइंटर को बिना किसी तर्क के ले जाता है और वापस लौटता है voidऔर फिर उसे कॉल करता है। फ़ंक्शन पॉइंटर्स कैसे काम करते हैं, इसके कारण पॉइंटर को डीफ़्रॉन्डिंग करने की आवश्यकता नहीं है।

एक स्पष्टीकरण:

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

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