एक सी कार्यान्वयन की अधिकतम कम्प्यूटेशनल शक्ति


28

यदि हम पुस्तक (या यदि आप चाहें तो भाषा विनिर्देश के किसी अन्य संस्करण) पर जाते हैं, तो सी कार्यान्वयन के लिए कितनी कम्प्यूटेशनल शक्ति हो सकती है?

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

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

मेरी प्रारंभिक प्रतिक्रिया यह थी कि C कार्यान्वयन परिमित ऑटोमेटन से अधिक कुछ नहीं है, क्योंकि इसमें पता योग्य मेमोरी की मात्रा की सीमा होती है (आप sizeof(char*) * CHAR_BITसंग्रहण के बिट्स से अधिक पता नहीं कर सकते हैं , क्योंकि स्टोर किए जाने पर अलग-अलग मेमोरी एड्रेस के अलग-अलग बिट पैटर्न होने चाहिए। एक बाइट पॉइंटर में)।

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

क्या ये सही है? क्या आप अधिक शक्तिशाली सी कार्यान्वयन पा सकते हैं? क्या ट्यूरिंग-पूर्ण सी कार्यान्वयन मौजूद है?


4
@ क्या: जैसा कि गिल्स ने समझाया है, ऐसा लगता है कि आपके पास अनबाउंड मेमोरी हो सकती है, लेकिन इसे सीधे संबोधित करने का कोई तरीका नहीं है।
जुका सुओमेला

2
आपके स्पष्टीकरण से ऐसा लगता है कि किसी भी सी कार्यान्वयन को केवल नियतात्मक पुशडाउन ऑटोमेटा द्वारा स्वीकार की जाने वाली भाषाओं को स्वीकार करने के लिए प्रोग्राम किया जा सकता है , जो कि संदर्भ-मुक्त भाषाओं से भी कमजोर हैं। हालाँकि यह अवलोकन मेरी राय में बहुत कम रुचि रखता है, क्योंकि यह प्रश्न स्पर्शोन्मुख दवाओं की गलत व्याख्या है।
वॉरेन शूडी

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

7
वैसे, टैग "मनोरंजक" (या हम जो भी अजीब पहेली के लिए उपयोग कर रहे हैं) को जोड़ना एक अच्छा विचार हो सकता है ताकि लोग इसे बहुत गंभीरता से न लें। यह स्पष्ट रूप से पूछने के लिए "गलत प्रश्न" है, लेकिन फिर भी मैंने इसे मनोरंजक और पेचीदा पाया। :)
जुका सुओमेला

2
@ जुक्का: अच्छा विचार है। उदाहरण के लिए, X पर ओवरफ्लो = टेप पर X / 3 लिखें और दिशा X% 3 में आगे बढ़ें, अंडरफ्लो = टेप पर प्रतीक के अनुरूप सिग्नल को ट्रिगर करें। यह एक गाली जैसा लगता है, लेकिन यह निश्चित रूप से मेरे सवाल की भावना में है। क्या आप इसे उत्तर के रूप में लिख सकते हैं? (माताओं: ऐसा नहीं है कि मैं इस तरह के अन्य चतुर सुझावों को हतोत्साहित करना चाहता हूं!)
गाइल्स का SO- बुराई पर रोक '22

जवाबों:


8

जैसा कि प्रश्न में कहा गया है, मानक C के लिए आवश्यक है कि एक मान UCHAR_MAX मौजूद हो जैसे कि प्रत्येक प्रकार का चर unsigned charहमेशा 0 और UCHAR_MAX के बीच एक मान रखेगा। इसके लिए यह आवश्यक है कि प्रत्येक गतिशील रूप से आवंटित वस्तु को बाइट्स के अनुक्रम द्वारा दर्शाया जाए जो unsigned char*कि प्रकार के सूचक के माध्यम से पहचाने जाने योग्य है , और यह एक निरंतरता है sizeof(unsigned char*)कि उस प्रकार के प्रत्येक सूचक प्रकार के sizeof(unsigned char *)मूल्यों के अनुक्रम द्वारा पहचाने जाने योग्य हो unsigned char। एक साथ गतिशील रूप से आवंटित की जा सकने वाली वस्तुओं की संख्या इस प्रकार । कुछ भी नहीं एक सैद्धांतिक संकलक को उन स्थिरांक के मूल्यों को निर्दिष्ट करने से रोक देगा ताकि 10 10 से अधिक 10 वस्तुओंका समर्थन किया जा सके, लेकिन सैद्धांतिक दृष्टिकोण से किसी भी बाध्य का अस्तित्व, चाहे कितना भी बड़ा हो, इसका मतलब कुछ भी अनंत नहीं है।UCHAR_MAXsizeof(unsigned char)101010

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

हालांकि, एक और संभावित शिकन है: यह आवश्यक है कि यदि कोई कार्यक्रम दो बिंदुओं से जुड़े चरित्र मानों के अंतर्निहित निश्चित-लंबाई अनुक्रमों की जांच करता है, तो वे अनुक्रम अद्वितीय होने चाहिए। क्योंकि केवल हैं UCHAR_MAXsizeof(unsigned char)वर्ण मानों के संभावित अनुक्रम, किसी भी प्रोग्राम ने कई वस्तुओं को अलग-अलग वस्तुओं से अलग बनाया जो कि सी मानक का अनुपालन नहीं कर सकते यदि कोड ने कभी उन बिंदुओं से जुड़े वर्णों के अनुक्रम की जांच की । यह कुछ मामलों में संभव होगा, हालांकि, एक संकलक के लिए यह निर्धारित करने के लिए कि कोई कोड कभी भी एक सूचक के साथ जुड़े पात्रों के अनुक्रम की जांच करने वाला नहीं था। यदि प्रत्येक "चार" वास्तव में किसी भी परिमित पूर्णांक को धारण करने में सक्षम था, और मशीन की मेमोरी पूर्णांक का एक अनंत-अनंत क्रम था [एक असीमित-टेप ट्यूरिंग मशीन दी गई, तो कोई भी ऐसी मशीन का अनुकरण कर सकता है, हालांकि यह वास्तव में धीमा होगा], फिर वास्तव में सी को ट्यूरिंग-पूर्ण भाषा बनाना संभव होगा।


ऐसी मशीन के साथ, क्या आकार (चार) वापसी होगी?
TLW

1
@TLW: किसी भी अन्य मशीन के रूप में एक ही: 1. CHAR_BITS और CHAR_MAX मैक्रोज़ थोड़ा अधिक समस्याग्रस्त होगा, हालाँकि; मानक उन प्रकारों की अवधारणा के लिए अनुमति नहीं देगा जिनकी कोई सीमा नहीं है।
सुपरकैट

वूप्स, मेरा मतलब था CHAR_BITS, जैसा कि आपने कहा, क्षमा करें।
TLW

7

C11 के (वैकल्पिक) थ्रेडिंग लाइब्रेरी के साथ, असीमित पुनरावृत्ति की गहराई को देखते हुए ट्यूरिंग पूर्ण कार्यान्वयन करना संभव है।

एक नया धागा बनाने से एक दूसरे स्टैक की पैदावार होती है; ट्यूरिंग पूर्णता के लिए दो स्टैक पर्याप्त हैं। एक स्टैक यह दर्शाता है कि सिर के बाईं ओर क्या है, दूसरा स्टैक दाईं ओर क्या है।


लेकिन केवल एक दिशा में एक टेप के साथ ट्यूरिंग मशीनों में प्रगति करना उतना ही शक्तिशाली है जितना कि ट्यूरिंग मशीनों में एक टेप के साथ असीम रूप से दो दिशाओं में प्रगति करना। इसके अलावा, एक अनुसूचक द्वारा कई थ्रेड्स का अनुकरण किया जा सकता है। वैसे भी, हमें थ्रेडिंग लाइब्रेरी की आवश्यकता नहीं है।
18

3

मुझे लगता है कि यह ट्यूरिंग पूरा हो गया है : हम एक प्रोग्राम लिख सकते हैं जो इस ट्रिक का उपयोग करके UTM का अनुकरण करता है (मैंने जल्दी से कोड को हाथ से लिखा था इसलिए शायद कुछ सिंटैक्स त्रुटियां हैं ... लेकिन मुझे आशा है कि तर्क में कोई (प्रमुख) त्रुटियां नहीं हैं :-)

  • एक संरचना को परिभाषित करें जिसका उपयोग टेप प्रतिनिधित्व के लिए एक डबल लिंक की गई सूची के रूप में किया जा सकता है
    टाइपडीएफ संरचना {
      cell_t * पूर्व; // सेल बाईं ओर
      cell_t * succ; // सेल दाईं ओर
      इंट वाल; // सेल वैल्यू
    } सेल_टी 

headएक करने के लिए एक सूचक हो जाएगा cell_tसंरचना

  • एक संरचना को परिभाषित करें जिसका उपयोग वर्तमान स्थिति और एक ध्वज को संग्रहीत करने के लिए किया जा सकता है
    टंकण संरचना {
      इंट स्टेट;
      int झंडा;
    } info_t 
  • तब एक एकल लूप फ़ंक्शन को परिभाषित करता है जो एक यूनिवर्सल टीएम का अनुकरण करता है जब सिर डबल लिंक्ड सूची की सीमाओं के बीच होता है; जब सिर ने सीमा रेखा को info_t संरचना (HIT_LEFT, HIT_RIGHT) के झंडे पर सेट किया और वापस लौटा:
शून्य simulate_UTM (cell_t * सिर, info_t * जानकारी) {
  जबकि (सच्चा) {
    सिर-> वैल = UTM_nextsymbol [जानकारी-> राज्य, सिर-> वैल]; // प्रतीक लिखें
    info-> state = UTM_nextstate [info-> state, head-> val]; // अगला राज्य
    if (जानकारी-> राज्य == HALT_STATE) {// प्रिंट अगर स्वीकार और बाहर निकलें कार्यक्रम
       putchar ((जानकारी-> राज्य == ACCEPT_STATE)? '1': '0');
       बाहर निकलने के (0);
    }
    int चाल = UTM_nextmove [जानकारी-> राज्य, प्रमुख-> वैल];
    अगर (चाल == MOVE_LEFT) {
      सिर = सिर-> पूर्व; // बाएं खिसको
      if (head == NULL) {जानकारी-> झंडा = HIT_LEFT; वापसी; }
    } अन्य {
      सिर = सिर-> succ; // दाएँ चले
      if (head == NULL) {जानकारी-> झंडा = HIT_RIGHT; वापसी; }
    }
  } // अभी भी सीमा में ... चलते हैं
}
  • फिर एक पुनरावर्ती फ़ंक्शन को परिभाषित करें जो पहले सिमुलेशन UTM रूटीन को कॉल करता है और फिर टेप को विस्तारित करने की आवश्यकता होने पर खुद को पुन: कॉल करता है; जब टेप को शीर्ष (HIT_RIGHT) पर विस्तारित करने की आवश्यकता होती है, तो कोई समस्या नहीं होती है, जब इसे नीचे (HIT_LEFT) पर स्थानांतरित करने की आवश्यकता होती है, बस डबल लिंक की गई सूची का उपयोग करके कोशिकाओं के मूल्यों को स्थानांतरित करें:
शून्य स्टेकर (cell_t * top, cell_t * bottom, cell_t * head, info_t * info) {
  simulate_UTM (प्रमुख, जानकारी);
  cell_t newcell; // नई सेल
  newcell.pred = top; // नई सेल के साथ डबल लिंक्ड सूची को अपडेट करें
  newcell.succ = NULL;
  शीर्ष-> succ = & newcell;
  newcell.val = EMPTY_SYMBOL;

  स्विच (जानकारी-> हिट) {
    मामला HIT_RIGHT:
      स्टेकर (& newcell, bottom, newcell, info);
      टूटना;
    मामला HIT_BOTTOM:
      cell_t * tmp = newcell;
      जबकि (tmp-> पूर्व! = NULL) {// मान बदलें
        tmp-> val = tmp-> पूर्व-> val;
        tmp = tmp-> pred;
      }
      tmp-> val = EMPTY_SYMBOL;
      स्टेकर (और न्यूसेल, नीचे, नीचे, जानकारी);
      टूटना;
  }
}
  • प्रारंभिक टेप एक साधारण पुनरावर्ती फ़ंक्शन से भरा जा सकता है जो डबल लिंक की गई सूची बनाता है और तब stackerफ़ंक्शन को कॉल करता है जब वह इनपुट टेप के अंतिम प्रतीक (रीडच का उपयोग करके) को पढ़ता है
शून्य init_tape (cell_t * top, cell_t * निचला, info_t * जानकारी) {
  cell_t newcell;
  int c = readchar ();
  if (c == END_OF_INPUT) स्टेकर (और ऊपर, नीचे, नीचे, जानकारी); // कोई और प्रतीक नहीं, प्रारंभ करें
  newcell.pred = top;
  if (शीर्ष! = NULL) top.succ = & newcell; और नीचे = & newcell;
  init_tape (& newcell, bottom, info);
}

संपादित करें: इसके बारे में थोड़ा सोचने के बाद, संकेत के साथ एक समस्या है ...

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


3
stackernewcellstacker2n/sns=sizeof(cell_t)

@ गिल्स: आप सही कह रहे हैं (मेरा संपादन देखें); यदि आप पुनरावृत्ति की गहराई को सीमित करते हैं तो आपको एक परिमित ऑटोमेटन मिलता है
Marzio De Biasi

@MarzioDeBiasi नहीं, वह गलत है क्योंकि वह एक ठोस कार्यान्वयन को संदर्भित करता है जो मानक निर्धारित नहीं करता है। वास्तव में, सी में पुनरावृत्ति की गहराई के लिए कोई सैद्धांतिक सीमा नहीं है । सीमित-स्टैक-आधारित कार्यान्वयन का उपयोग करने का एक विकल्प भाषा की सैद्धांतिक सीमाओं के बारे में कुछ नहीं कहता है। लेकिन ट्यूरिंग-पूर्णता एक सैद्धांतिक सीमा है।
19

0

जब तक आपके पास एक अनबाउंड कॉल-स्टैक आकार होता है तब तक आप कॉल-स्टैक पर अपने टेप को एन्कोड कर सकते हैं, और फ़ंक्शन-कॉल से वापस आए बिना स्टैक-पॉइंटर को रिवाइंड करके इसे यादृच्छिक-एक्सेस कर सकते हैं।

एडिट : यदि आप केवल राम का उपयोग कर सकते हैं, जो परिमित है, तो यह निर्माण अब काम नहीं करता है, इसलिए नीचे देखें।

हालाँकि यह अत्यधिक संदिग्ध है कि आपका स्टैक अनंत क्यों हो सकता है लेकिन आंतरिक राम नहीं है। इसलिए वास्तव में मैं कहूंगा कि आप सभी नियमित भाषाओं को भी नहीं पहचान सकते हैं, क्योंकि राज्यों की संख्या बंधी हुई है (यदि आप अनंत ढेर का फायदा उठाने के लिए स्टैक-रिवाइंड ट्रिक की गिनती नहीं करते हैं)।

मैं यह भी अनुमान लगाऊंगा कि जिन भाषाओं को आप पहचान सकते हैं, वह परिमित है (भले ही भाषाएँ स्वयं अनंत हों, उदाहरण के a*लिए ठीक है, लेकिन b^kकेवल परिमित संख्याओं के लिए काम करती है k)।

संपादित करें : यह सच नहीं है, क्योंकि आप वर्तमान राज्य को अतिरिक्त कार्यों में संलग्न कर सकते हैं, इसलिए आप सभी नियमित भाषाओं को पहचान सकते हैं।

आप ज्यादातर सभी टाइप -2 भाषाओं को एक ही कारण से प्राप्त कर सकते हैं, लेकिन मुझे यकीन नहीं है कि आप कॉल-स्टैक पर स्टेट और स्टैक-कॉन्स्टेंट दोनों को डाल सकते हैं । लेकिन एक सामान्य नोट पर, आप प्रभावी रूप से राम के बारे में भूल सकते हैं, क्योंकि आप हमेशा ऑटोमेटन के आकार को माप सकते हैं ताकि आपकी वर्णमाला राम की क्षमता से अधिक हो। तो अगर आप केवल एक स्टैक के साथ एक टीएम का अनुकरण कर सकते हैं, तो टाइप -2 बराबर टाइप -0 होगा, है ना?


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

मैंने स्टैक-पॉइंटर के उपयोग को बाहर करने के लिए अपना उत्तर संशोधित किया है।
बिटमस्क

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

0

मैंने एक बार इस बारे में सोचा था, और अपेक्षित शब्दार्थों का उपयोग करके एक गैर-संदर्भ-मुक्त भाषा को लागू करने का प्रयास करने का निर्णय लिया; कार्यान्वयन का मुख्य भाग निम्नलिखित कार्य है:

void *it;

void read_triple(void *back)
{
  if(read_a()) read_triple(&back);
  else reject();
  for(it = back; it != NULL; it = *it)
     if(!read_b()) reject();
  if(read_c()) return;
  else reject();
}

{anbncn}

कम से कम, मुझे लगता है कि यह काम करता है। यह हो सकता है कि मैं कुछ मौलिक गलती कर रहा हूं, हालांकि।

एक निश्चित संस्करण:

void *it;

void read_triple(void *back)
{
  if(read_a()) read_triple(&back);
  else for(it = back; it != NULL; it = * (void **) it)
     if(!read_b()) reject();
  if(read_c()) return;
  else reject();
}

ठीक है, एक मौलिक गलती नहीं है, लेकिन it = *itइसके द्वारा प्रतिस्थापित किया जाना चाहिए it = * (void **) it, जैसा कि अन्यथा *itप्रकार का है void
बेन स्टैंडवेन

मुझे बहुत आश्चर्य होगा अगर कॉल स्टैक की तरह यात्रा करना सी में परिभाषित व्यवहार होगा
रादु ग्रिगोर

ओह, यह काम नहीं करेगा, क्योंकि पहले 'b' के कारण read_a () विफल होता है और इसलिए अस्वीकृति को ट्रिगर करता है।
बेन स्टेंडवेन

लेकिन इस फैशन को कॉल स्टैक की यात्रा करना वैध है, क्योंकि सी मानक कहता है: "ऐसी वस्तु के लिए [अर्थात स्वचालित भंडारण के साथ] जिसमें एक चर लंबाई सरणी प्रकार नहीं है, इसका जीवनकाल ब्लॉक में प्रवेश से फैलता है यह तब तक जुड़ा रहता है जब तक कि ब्लॉक का निष्पादन किसी भी तरह से समाप्त नहीं हो जाता है। (एक संलग्न ब्लॉक में प्रवेश करना या किसी फ़ंक्शन को कॉल करना निलंबित करता है, लेकिन समाप्त नहीं होता है, वर्तमान ब्लॉक का निष्पादन।) यदि ब्लॉक को पुनरावर्ती रूप से दर्ज किया जाता है, तो ऑब्जेक्ट का एक नया उदाहरण। हर बार बनाया जाता है। " तो read_triple की प्रत्येक कॉल एक नया पॉइंटर बनाएगी, जिसका उपयोग पुनरावृत्ति में किया जा सकता है।
बजे बेन स्टैंडवेन ओवन

2
2CHAR_BITsizeof(char*)

0

@ सुपरकैट के उत्तर की तर्ज पर:

C के अधूरेपन के दावों को लगता है कि अलग-अलग वस्तुओं के अलग-अलग पते होने चाहिए, और पते के सेट को परिमित होना चाहिए। जैसा @supercat लिखते हैं

जैसा कि सवाल में कहा गया है, मानक सी के लिए यह आवश्यक है कि एक मान मौजूद हो UCHAR_MAXजैसे कि टाइप किए गए चार का हर चर हमेशा 0 और UCHAR_MAX, के बीच एक मान रखेगा । इसके लिए यह आवश्यक है कि प्रत्येक गतिशील रूप से आवंटित वस्तु को बाइट्स के अनुक्रम द्वारा दर्शाया जाए जो कि टाइप अहस्ताक्षरित चार * के सूचक के माध्यम से पहचाने जाने योग्य है, और यह एक निरंतरता है sizeof(unsigned char*)कि उस प्रकार के प्रत्येक सूचक को टाइप किए गए sizeof(unsigned char *)मूल्यों के अनुक्रम द्वारा पहचाने जाने योग्य हो। चार।

unsigned char*N{0,1}sizeof(unsigned char*){0,1}sizeof(unsigned char)Nsizeof(unsigned char*)Nω

इस बिंदु पर, किसी को यह देखना चाहिए कि सी मानक वास्तव में इसकी अनुमति देगा।

sizeofZ


1
अभिन्न प्रकार के कई कार्यों को एक परिणाम के रूप में परिभाषित किया गया है जो "परिणाम प्रकार में अधिकतम प्रतिनिधित्व योग्य मूल्य से एक से कम modulo" है। यदि वह अधिकतम गैर-परिमित अध्यादेश है तो वह कैसे काम करेगा?
गाइल्स का SO- बुराई पर रोक

@ गिल्स यह एक दिलचस्प बिंदु है। यह वास्तव में स्पष्ट नहीं है कि किस शब्द का अर्थ क्या होगा uintptr_t p = (uintptr_t)sizeof(void*)(बिना किसी पूर्णांक के) में ओमेगा डालना। मुझे नहीं पता। हम 0 (या किसी अन्य संख्या) होने के परिणाम को परिभाषित करने के साथ दूर हो सकते हैं।
एलेक्सी बी।

1
uintptr_tअनंत भी होना पड़ेगा। ध्यान रहे, यह प्रकार वैकल्पिक है - लेकिन यदि आपके पास अलग-अलग सूचक मानों की अनंत संख्या है sizeof(void*), तो अनंत भी होना size_tचाहिए , इसलिए अनंत होना चाहिए। कमी के बारे में मेरी आपत्ति हालांकि इतनी स्पष्ट नहीं है - यह केवल खेल में आता है यदि कोई अतिप्रवाह है, लेकिन यदि आप अनंत प्रकारों की अनुमति देते हैं तो वे कभी भी अतिप्रवाह नहीं कर सकते हैं। लेकिन मनोरंजक हाथ पर, प्रत्येक प्रकार का एक न्यूनतम और अधिकतम मूल्य होता है, जो कि जहां तक ​​मैं बता सकता हूं कि UINT_MAX+1अतिप्रवाह होना चाहिए।
गिल्स एसओ- बुराई को रोकना

एक अच्छी बात भी। वास्तव में, हमें प्रकार (संकेत और size_t) का एक गुच्छा मिलता है जो ℤ, would {ω} की तरह होगा, तो उनके आधार पर ℤ, bunch, या उनके आधार पर कुछ निर्माण होना चाहिए। अब, अगर इन प्रकारों में से कुछ के लिए, मानक को अधिकतम मूल्य (PTR_MAX या ऐसा कुछ) परिभाषित करने के लिए एक मैक्रो की आवश्यकता होती है, तो चीजें बालों वाली हो जाएंगी। लेकिन अब तक मैं केवल गैर-पॉइंटर प्रकारों के लिए MIN / MAX मैक्रो की आवश्यकता को निधि देने में सक्षम था।
एलेक्सी बी।

जांच करने की एक अन्य संभावना दोनों size_tऔर सूचक प्रकारों को to ∪ {।} के रूप में परिभाषित करना है। इससे मिनट / अधिकतम समस्या से छुटकारा मिलता है। अतिप्रवाह शब्दार्थ के साथ मुद्दा अभी भी बना हुआ है। का शब्दार्थ क्या होना चाहिए यह uint x = (uint)ωमेरे लिए स्पष्ट नहीं है। फिर से, हम लापरवाही से 0 ले सकते हैं, लेकिन यह थोड़ा बदसूरत दिखता है।
एलेक्सी बी।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.