मुझे यकीन नहीं है, लेकिन मुझे लगता है कि इसका जवाब नहीं है, बल्कि सूक्ष्म कारणों से। मैंने कुछ साल पहले सैद्धांतिक कंप्यूटर विज्ञान पर पूछा था और मुझे इसका जवाब नहीं मिला कि मैं यहां क्या पेश करूंगा।
अधिकांश प्रोग्रामिंग भाषाओं में, आप एक ट्यूरिंग मशीन का अनुकरण कर सकते हैं:
- स्मृति के लिए एक परिमित राशि का उपयोग करने वाले कार्यक्रम के साथ परिमित ऑटोमेटन का अनुकरण करना;
- वर्तमान स्थिति से पहले और बाद में टेप की सामग्री का प्रतिनिधित्व करते हुए, पूर्णांकों की लिंक्ड सूचियों की एक जोड़ी के साथ टेप का अनुकरण करना। पॉइंटर को हिलाने का मतलब है सूची में से किसी एक सूची के प्रमुख को दूसरी सूची में स्थानांतरित करना।
यदि टेप बहुत लंबा हो जाता है, तो कंप्यूटर पर चलने वाला एक ठोस कार्यान्वयन मेमोरी से बाहर हो जाएगा, लेकिन एक आदर्श कार्यान्वयन ट्यूरिंग मशीन को ईमानदारी से निष्पादित कर सकता है। यह पेन और पेपर के साथ, या अधिक मेमोरी वाले कंप्यूटर को खरीदकर, और एक कंपाइलर प्रति शब्द और अधिक बिट्स के साथ आर्किटेक्चर को लक्षित कर सकता है, और यदि प्रोग्राम कभी मेमोरी से बाहर निकलता है।
यह C में काम नहीं करता है क्योंकि लिंक की गई सूची को हमेशा के लिए विकसित करना असंभव है: नोड्स की संख्या पर हमेशा कुछ सीमा होती है।
यह समझाने के लिए कि, मुझे सबसे पहले यह समझाने की आवश्यकता है कि सी कार्यान्वयन क्या है। C वास्तव में प्रोग्रामिंग भाषाओं का परिवार है। आईएसओ सी मानक (अधिक सटीक, इस मानक के विशेष संस्करण) परिभाषित करता है वाक्य रचना और शब्दों भाषाओं प्रोग्रामिंग के एक परिवार (औपचारिकता के स्तर है कि अंग्रेजी की अनुमति देता है के साथ)। C में बहुत अधिक अपरिभाषित व्यवहार और कार्यान्वयन-परिभाषित व्यवहार है। C का एक "कार्यान्वयन" सभी कार्यान्वयन-परिभाषित व्यवहार (कोड करने के लिए चीजों की सूची C99 के लिए परिशिष्ट J में है) को संहिताबद्ध करता है। C का प्रत्येक कार्यान्वयन एक अलग प्रोग्रामिंग भाषा है। ध्यान दें कि "कार्यान्वयन" शब्द का अर्थ थोड़ा अजीब है: इसका वास्तव में क्या मतलब है एक भाषा संस्करण है, एक ही भाषा संस्करण को लागू करने वाले कई अलग-अलग संकलक कार्यक्रम हो सकते हैं।
सी के दिए गए कार्यान्वयन में, एक बाइट में संभव मान हैं। सभी डेटा बाइट्स के एक सरणी के रूप में प्रतिनिधित्व कर सकते हैं: एक प्रकार में अधिकतम
संभव मान हैं। यह संख्या C के विभिन्न कार्यान्वयनों में भिन्न है, लेकिन C के दिए गए कार्यान्वयन के लिए, यह एक स्थिर है। 2 CHAR_BIT × आकार (t)2CHAR_BITt
2CHAR_BIT×sizeof(t)
विशेष रूप से, पॉइंटर्स केवल मानों पर ले सकते हैं। इसका मतलब यह है कि पता योग्य वस्तुओं की एक परिमित अधिकतम संख्या है।2CHAR_BIT×sizeof(void*)
के मान CHAR_BIT
और sizeof(void*)
अवलोकन योग्य हैं, इसलिए यदि आप स्मृति से बाहर निकलते हैं, तो आप उन मापदंडों के लिए अपने प्रोग्राम को बड़े मानों के साथ चलाना फिर से शुरू नहीं कर सकते। आप एक अलग प्रोग्रामिंग भाषा - एक अलग सी कार्यान्वयन के तहत कार्यक्रम चला रहे होंगे।
यदि किसी भाषा में प्रोग्राम केवल एक सीमित संख्या में राज्य हो सकते हैं, तो प्रोग्रामिंग भाषा परिमित ऑटोमेटा से अधिक अभिव्यंजक नहीं है। सी के टुकड़ा है कि पता भंडारण के लिए प्रतिबंधित है केवल ज्यादा से ज्यादा की अनुमति देता है कार्यक्रम राज्यों में का सार वाक्य रचना पेड़ के आकार है कार्यक्रम (नियंत्रण प्रवाह की स्थिति का प्रतिनिधित्व करता है), इसलिए इस कार्यक्रम को कई राज्यों के साथ परिमित ऑटोमेटन द्वारा अनुकरण किया जा सकता है। यदि C अधिक अभिव्यंजक है, तो इसे अन्य विशेषताओं के उपयोग के माध्यम से होना चाहिए। nn×2CHAR_BIT×sizeof(void*)n
सी सीधे अधिकतम पुनरावृत्ति गहराई नहीं लगाता है। एक कार्यान्वयन में अधिकतम करने की अनुमति है, लेकिन यह भी एक नहीं होने की अनुमति है। लेकिन हम एक फ़ंक्शन कॉल और उसके माता-पिता के बीच कैसे संवाद करते हैं? यदि वे पते योग्य हैं, तो तर्क अच्छा नहीं है, क्योंकि यह अप्रत्यक्ष रूप से पुनरावृत्ति की गहराई को सीमित करेगा: यदि आपके पास कोई फ़ंक्शन है, int f(int x) { … f(…) …}
तो x
सक्रिय फ़्रेमों के सभी घटनाओं का f
अपना पता है और इसलिए नेस्टेड कॉल की संख्या संख्या से बाध्य है के लिए संभावित पते की x
।
एसी प्रोग्राम register
चर के रूप में गैर-पते योग्य भंडारण का उपयोग कर सकता है । "सामान्य" कार्यान्वयन में केवल एक छोटा, सीमित संख्या में चर हो सकते हैं, जिनमें कोई पता नहीं होता है, लेकिन सिद्धांत रूप में एक कार्यान्वयन अनबाउंड register
स्टोरेज की अनुमति दे सकता है । इस तरह के क्रियान्वयन में, आप किसी फ़ंक्शन के लिए पुनरावर्ती कॉल की एक अनबाउंड राशि बना सकते हैं, जब तक कि उसके तर्क हैं register
। लेकिन जब से तर्क हैं register
, आप उन्हें एक संकेतक नहीं बना सकते हैं, और इसलिए आपको उनके डेटा को स्पष्ट रूप से चारों ओर कॉपी करने की आवश्यकता है: आप केवल डेटा की एक सीमित मात्रा के आसपास से गुजर सकते हैं, न कि मनमाने ढंग से आकार की डेटा संरचना जो बिंदुओं से बनी होती है।
निर्बाध पुनरावृत्ति गहराई के साथ, और यह प्रतिबंध कि कोई फ़ंक्शन केवल अपने डायरेक्ट कॉलर ( register
तर्क) से डेटा प्राप्त कर सकता है और डेटा को उसके डायरेक्ट कॉलर (फ़ंक्शन रिटर्न वैल्यू) पर वापस ला सकता है, आपको नियतात्मक पुशडाउन ऑटोमेटा की शक्ति मिलती है ।
मुझे आगे जाने का रास्ता नहीं मिल रहा है।
(बेशक आप प्रोग्राम को टेप सामग्री को फ़ाइल इनपुट / आउटपुट फ़ंक्शन के माध्यम से बाह्य रूप से स्टोर कर सकते हैं। लेकिन तब आप यह नहीं पूछ रहे होंगे कि क्या सी ट्यूरिंग-पूर्ण है, लेकिन क्या सी प्लस एक अनंत भंडारण प्रणाली ट्यूरिंग-पूर्ण है, जो उत्तर एक उबाऊ "हाँ" है। आप एक ट्यूरिंग ऑरेकल होने के लिए भंडारण को परिभाषित कर सकते हैं - कॉल fopen("oracle", "r+")
, fwrite
प्रारंभिक टेप सामग्री और fread
अंतिम टेप सामग्री वापस।)