हमारे पास पश्चगामी वेतन वृद्धि क्यों है?


55

अस्वीकरण : मैं उपसर्ग और उपसर्ग वृद्धि के शब्दार्थ को अच्छी तरह से जानता हूं। तो कृपया मुझे मत समझाओ कि वे कैसे काम करते हैं।

स्टैक ओवरफ्लो पर सवाल पढ़ना, मैं मदद नहीं कर सकता लेकिन ध्यान दें कि प्रोग्रामर पोस्टफिक्स इंक्रीमेंट ऑपरेटर द्वारा बार-बार भ्रमित हो जाते हैं। इससे निम्नलिखित प्रश्न उठता है: क्या कोई उपयोग मामला है जहां पोस्टफिक्स इन्क्रीमेंट कोड गुणवत्ता के संदर्भ में वास्तविक लाभ प्रदान करता है?

एक उदाहरण के साथ अपने प्रश्न को स्पष्ट करता हूं। यहाँ एक सुपर-ट्रिक कार्यान्वयन है strcpy:

while (*dst++ = *src++);

लेकिन यह मेरी पुस्तक में बिल्कुल स्व-दस्तावेजीकरण कोड नहीं है (और यह सेंस कंपाइलर्स पर दो कष्टप्रद चेतावनी देता है)। तो निम्नलिखित विकल्प में क्या गलत है?

while (*dst = *src)
{
    ++src;
    ++dst;
}

हम तब स्थिति में भ्रामक असाइनमेंट से छुटकारा पा सकते हैं और पूरी तरह से चेतावनी-मुक्त कोड प्राप्त कर सकते हैं:

while (*src != '\0')
{
    *dst = *src;
    ++src;
    ++dst;
}
*dst = '\0';

(हां, मुझे पता है, srcऔर dstइन वैकल्पिक समाधानों में अलग-अलग समाप्ति मूल्य होंगे, लेकिन चूंकि strcpyलूप के तुरंत बाद लौटता है, इसलिए इस मामले में कोई फर्क नहीं पड़ता।)

ऐसा लगता है कि पोस्टफिक्स इन्क्रीमेंट का उद्देश्य कोड को जितना संभव हो सके बनाना है। मैं बस यह देखने में विफल रहता हूं कि यह ऐसी चीज है जिसके लिए हमें प्रयास करना चाहिए। यदि यह मूल रूप से प्रदर्शन के बारे में था, तो क्या यह आज भी प्रासंगिक है?


7
उपसर्ग संस्करण सबसे अधिक इस्तेमाल किया जाने वाला एक है, इसलिए यदि आप इसके खिलाफ एक मामला बनाने जा रहे हैं, तो बेहतर होगा कि यह बहुत मजबूत मामला हो। और आपका पहला उदाहरण एक पुआल आदमी का है, क्योंकि मुझे संदेह है कि कुछ लोग वास्तव में strcpyइस तरह से विधि का कोड करेंगे (उन कारणों के लिए जो आपने पहले ही उल्लेख किया है)।
रॉबर्ट हार्वे

4
क्यों या तो सब पर है?
जेम्स मैकनेलिस

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

4
हाँ, लेकिन फिर आप कभी भी ऐसा नहीं कर सकतेint c = 0; c++;
Biff MaGriff

4
@ कोडी: क्योंकि कुछ चीजें भ्रमित और उपयोगी दोनों हैं। वह स्वयं पोस्ट-इन्क्रीमेंट से भ्रमित नहीं है, वह इसकी उपयोगिता के बारे में भ्रमित है । हमारे पास ऐसी चीजें नहीं होनी चाहिए जो बेकार हैं, भ्रामक हैं या नहीं।
GManNickG

जवाबों:


23

हालांकि यह एक बार कुछ प्रदर्शन निहितार्थ था, मुझे लगता है कि असली कारण आपके इरादे को साफ-साफ व्यक्त करने के लिए है। असली सवाल यह है कि कुछ while (*d++=*s++);स्पष्ट रूप से मंशा व्यक्त करता है या नहीं। IMO, यह करता है, और मैं उन विकल्पों को खोजता हूं जो आप कम स्पष्ट प्रस्तुत करते हैं - लेकिन यह (आसानी से) खर्च किए गए दशकों का एक परिणाम हो सकता है कि चीजें कैसे की जाती हैं। K & R से C सीखा है (क्योंकि उस समय C पर लगभग कोई अन्य किताबें नहीं थीं ) शायद बहुत मदद करती हैं।

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

बेशक यह जहाज पर जाना संभव है, लेकिन मुझे नहीं लगता कि यह है। विशेष रूप से, मुझे लगता है कि कोड की एक पंक्ति को समझना अत्यंत कठिन या समय लेने वाला हो जाता है - विशेष रूप से, जब कोड की कम पंक्तियों को समझने से अधिक लाइनों को समझने की तुलना में अधिक प्रयास की खपत होती है। यह लिस्प और एपीएल में अक्सर होता है, लेकिन यहां मामला होने के लिए (कम से कम मेरे लिए) प्रतीत नहीं होता है।

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


12
+1 इंगित करने के लिए कि हम में से कुछ को पढ़ने के लिए ट्रिक संस्करण आसान है। :-)

1
यदि आपको अपने कुछ संकलक की चेतावनी पसंद नहीं है (और कुछ के बिना मैं कर सकता था - गंभीरता से, मेरे पास टाइप करने का मतलब है if(x = y), मैं कसम खाता हूं!) आपको अपने संकलक की चेतावनी के विकल्पों को समायोजित करना चाहिए ताकि आप गलती से याद न करें। चेतावनी आप करते हैं पसंद है।

4
@ ब्रूक्स मूसा: मैं उस बारे में बहुत कम उत्साहित हूं । मुझे कंपाइलर की कमियों के लिए अपने कोड को प्रदूषित करना पसंद नहीं है।
जेरी कॉफ़िन

1
@ जेरी, @ क्रिस: यह एनोटेशन उस मामले के लिए अभिप्रेत है जहां आपको लगता है कि चेतावनी आमतौर पर एक अच्छी बात है, लेकिन आप नहीं चाहते कि यह एक विशेष लाइन पर लागू हो जो कुछ असामान्य कर रही है। यदि आप चेतावनी कभी नहीं चाहते हैं और इसे एक कमी मानते हैं -Wno-X, तो उपयोग करें , लेकिन यदि आप केवल इसके लिए एक अपवाद बनाना चाहते हैं और चेतावनी को हर जगह लागू करना चाहते हैं, तो यह आर्कैन हूप-जंपिंग का उपयोग करने की तुलना में बहुत अधिक समझदार है जैसे क्रिस को संदर्भित करता है ।

1
@ ब्रोक्स: डबल कोष्ठक और (void)xमौन अप्रयुक्त चेतावनियों के लिए काफी अच्छी तरह से ज्ञात चेतावनियाँ हैं जो अन्यथा उपयोगी चेतावनियाँ हैं। एनोटेशन कुछ हद तक अच्छा लगता है pragmas, न कि सबसे अच्छा पोर्टेबल: /
मैथ्यू एम।

32

यह, एक गलत बात है, एक हार्डवेयर बात थी


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

हालाँकि C को शुरुआती और कम दबाव वाली मशीनों के रूप में विकसित किया गया था, लेकिन C और Unix ने पीडीपी -11 के मेमोरी-प्रबंधित मॉडल के साथ सबसे पहले सापेक्ष बड़े-समय को मारा। अपने दिन में ये अपेक्षाकृत महत्वपूर्ण कंप्यूटर थे और यूनिक्स -11 के लिए उपलब्ध अन्य 7 क्रमी ऑपरेटिंग सिस्टमों की तुलना में कहीं बेहतर - घातीय रूप से बेहतर था।

और, ऐसा होता है, कि पीडीपी -11 पर,

*--p

तथा

*p++

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

एक परिणाम के रूप में, डिजाइन पैटर्न क्योंकि सी मुहावरे जो सी मानसिक मैक्रोज़ बन गए।

यह कुछ ऐसा है जैसे चर घोषित करना सही है {... नहीं क्योंकि C89 चालू था, यह एक आवश्यकता है, लेकिन यह अब एक कोड पैटर्न है।

अद्यतन: जाहिर है, मुख्य कारण *p++भाषा में है क्योंकि यह वही है जो अक्सर ऐसा करना चाहता है। कोड पैटर्न की लोकप्रियता को लोकप्रिय हार्डवेयर द्वारा प्रबलित किया गया था जो पीडीपी -11 के आने से पहले डिज़ाइन की गई भाषा के पहले से मौजूद पैटर्न के साथ आया और मेल खाता था।

इन दिनों यह कोई फर्क नहीं जो पैटर्न का उपयोग करें, या आप अनुक्रमण का उपयोग करता है, तो बनाता है, और हम आम तौर पर वैसे भी एक उच्च स्तर पर कार्यक्रम है, लेकिन यह उन 0.001GHz मशीनों पर एक बहुत मायने रखता रहा हो और के अलावा और कुछ का उपयोग कर *--xया *x++आप मतलब था PDP-11 को "नहीं मिला", और हो सकता है कि आपके पास आने वाले लोग और कहें कि "क्या आप जानते हैं कि ..." :-)


25
विकिपीडिया कहते हैं: "एक (गलत) लोक मिथक है कि PDP-11 के अनुदेश सेट वास्तुकला सी प्रोग्रामिंग भाषा का मुहावरेदार प्रयोग प्रभावित है PDP-11 के वेतन वृद्धि और घटती को संबोधित मोड के अनुरूप हैं। −−iऔर i++सी हैं में निर्माणों iऔर jदोनों रजिस्टर चर थे, एक अभिव्यक्ति जैसे कि *(−−i) = *(j++)एक मशीन निर्देश के लिए संकलित किया जा सकता है। [...] डेनिस रिची ने इस लोक मिथक का विरोधाभासी रूप से विरोधाभास किया। [सी भाषा का विकास ] "
fredoverflow

3
हुह (फ्रेडोवरफ्लो की टिप्पणी में दिए गए लिंक से): "लोग अक्सर अनुमान लगाते हैं कि वे डीईसी पीडीपी -11 द्वारा प्रदान किए गए ऑटो-इन्क्रीमेंट और ऑटो-डिक्रीमेंट एड्रेस मोड का उपयोग करने के लिए बनाए गए थे, जिस पर सी और यूनिक्स पहले लोकप्रिय थे। यह ऐतिहासिक रूप से है। असंभव, चूंकि बी विकसित होने पर कोई पीडीपी -11 नहीं था। पीडीपी -7, हालांकि, कुछ `ऑटो-इन्क्रीमेंट 'मेमोरी सेल थे, इस संपत्ति के साथ कि उनके माध्यम से एक अप्रत्यक्ष स्मृति संदर्भ सेल को बढ़ाता था। थॉम्पसन के लिए ऐसे ऑपरेटरों का सुझाव दिया; उन्हें उपसर्ग और पोस्टफ़िक्स दोनों बनाने का सामान्यीकरण उनका अपना था।]

3
डीएमआर ने केवल यह कहा कि पीडीपी -11 वह कारण नहीं था जिसे सी में जोड़ा गया था। मैंने भी कहा। मैंने जो कहा वह पीडीपी -11 पर लाभ के लिए इस्तेमाल किया गया और उस सटीक कारण के लिए एक लोकप्रिय डिजाइन पैटर्न बन गया। अगर विकिपीडिया विरोधाभासी है तो वे बस गलत हैं, लेकिन मैं इसे इस तरह से नहीं पढ़ता हूं। यह उस डब्ल्यू पेज पर खराब तरीके से बनाया गया है।
DigitalRoss

3
@FredOverflow। मुझे लगता है कि आपने गलत समझा कि "लोक मिथक" क्या है। मिथक यह है कि C को उन 11 ऑप्स का शोषण करने के लिए डिज़ाइन किया गया था, न कि वे मौजूद नहीं हैं और ऐसा नहीं है कि कोड पैटर्न लोकप्रिय नहीं हुआ क्योंकि सभी जानते थे कि वे 11 अच्छी तरह से मैप करते थे। यदि यह स्पष्ट नहीं है: पीडीपी -11 वास्तव में उन दो मोडों को हार्डवेयर में लागू करता है जो लगभग हर निर्देश के लिए एक एड्रेसिंग मोड के रूप में लागू होते हैं, और यह वास्तव में पहली महत्वपूर्ण मशीन सी थी।
DigitalRoss

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

14

उपसर्ग और पोस्टफ़िक्स --और ++ऑपरेटरों को केन थॉम्पसन द्वारा बी भाषा (सी के पूर्ववर्ती) में पेश किया गया था - और नहीं, वे पीडीपी -11 से प्रेरित नहीं थे, जो उस समय मौजूद नहीं थे।

डेनिस रिची द्वारा "द डेवलपमेंट ऑफ़ द सी लैंग्वेज" का उद्धरण :

थॉम्पसन ++और का आविष्कार करके एक कदम आगे चला गया--ऑपरेटरों, जो वेतन वृद्धि या गिरावट; उनके उपसर्ग या उपसर्ग की स्थिति निर्धारित करती है कि क्या ऑपरेंड के मान को नोट करने से पहले या बाद में परिवर्तन होता है। वे बी के शुरुआती संस्करणों में नहीं थे, लेकिन रास्ते में दिखाई दिए। लोग अक्सर अनुमान लगाते हैं कि वे डीईसी पीडीपी -11 द्वारा प्रदान किए गए ऑटो-इन्क्रीमेंट और ऑटो-डिक्रीमेंट एड्रेस मोड का उपयोग करने के लिए बनाए गए थे, जिस पर सी और यूनिक्स पहले लोकप्रिय हो गए थे। यह ऐतिहासिक रूप से असंभव है, क्योंकि बी विकसित होने पर कोई पीडीपी -11 नहीं था। हालाँकि, PDP-7 में कुछ 'ऑटो-इन्क्रीमेंट' मेमोरी सेल होते हैं, इस प्रॉपर्टी के साथ कि उनके माध्यम से एक इनडायरेक्ट मेमोरी रेफरेंस सेल को बढ़ाता है। इस सुविधा ने संभवतः थॉम्पसन को ऐसे ऑपरेटरों का सुझाव दिया; उन्हें उपसर्ग और उपसर्ग दोनों बनाने के लिए सामान्यीकरण उनका अपना था। वास्तव में,++xसे छोटा था x=x+1


8
नहीं, मैं केन थॉम्पसन से संबंधित नहीं हूं।
कीथ थॉम्पसन

इस बहुत ही रोचक संदर्भ के लिए धन्यवाद! यह मूल K & R से मेरे उद्धरण की पुष्टि करता है जिसने तकनीकी अनुकूलन के बजाय कॉम्पैक्टनेस के लक्ष्य का सुझाव दिया। हालांकि मुझे नहीं पता था कि ये ऑपरेटर पहले से ही बी
क्रिस्टोफ़

@BenPen जहां तक ​​मुझे पता है कि अलग-अलग SE साइट पर डुप्लिकेट होने पर प्रश्नों को बंद करने की कोई नीति नहीं है , जब तक कि दोनों प्रश्न उनके संबंधित साइटों पर फिट नहीं हो जाते।
आयुध

दिलचस्प ... प्रोग्रामर एक निश्चित रूप से एक सवाल के करीब नहीं है।
बेनपेन

@ बेनपेन: स्टैक ओवरफ्लो प्रश्न का स्वीकृत उत्तर पहले से ही मेरे द्वारा किए गए स्रोत का हवाला देता है (हालाँकि यह उतना नहीं है)।
कीथ थॉम्पसन

6

Postincrement ऑपरेटर का अस्तित्व के लिए स्पष्ट कारण तो यह है कि आप की तरह भाव लिखने के लिए नहीं है (++x,x-1)या (x+=1,x-1)हर जगह या बेकार में कई बयानों में बाहर आसानी से समझ में दुष्प्रभावों के साथ तुच्छ बयान को अलग। यहाँ कुछ उदाहरण हैं:

while (*s) x+=*s++-'0';

if (x) *s++='.';

जब भी आगे की दिशा में एक स्ट्रिंग को पढ़ना या लिखना होता है, तो पुनरावृत्ति, और पूर्वनिर्धारण नहीं, लगभग हमेशा प्राकृतिक संचालन होता है। मैंने लगभग कभी भी वास्तविक दुनिया के पूर्व-उपयोग के लिए उपयोग नहीं किया है, और मैंने केवल पूर्व-उपयोग के लिए जो प्रमुख उपयोग पाया है वह संख्याओं को स्ट्रिंग्स में परिवर्तित कर रहा है (क्योंकि मानव लेखन प्रणाली पीछे की ओर संख्याएं लिखती है)।

संपादित करें: वास्तव में यह बहुत बदसूरत नहीं होगा; (++x,x-1)आप के बजाय पाठ्यक्रम का उपयोग कर सकते हैं ++x-1या (x+=1)-1। अभी भी x++अधिक पठनीय है।


आपको उन अभिव्यक्तियों के बारे में सावधान रहना होगा जब आप दो अनुक्रम बिंदुओं के बीच एक चर को संशोधित और पढ़ रहे हैं। जिस क्रम में उन भावों का मूल्यांकन किया जाता है, उसकी गारंटी नहीं होती है।

@Snowman: कौन सा? मुझे अपने उत्तर में ऐसे कोई मुद्दे नहीं दिखते।
आर ..

यदि आपके पास कुछ ऐसा है (++x,x-1)(फ़ंक्शन कॉल, हो सकता है?)

@Snowman: यह एक फ़ंक्शन कॉल नहीं है। यह सी कॉमा ऑपरेटर है, जो एक अनुक्रम बिंदु है, जो वरीयता को नियंत्रित करने के लिए कोष्ठक है। परिणाम x++ज्यादातर मामलों में एक ही है (एक अपवाद: xरैंक से कम के साथ एक अहस्ताक्षरित प्रकार है intऔर प्रारंभिक मूल्य xउस प्रकार का अधिकतम मूल्य है)।
आर ..

आह, मुश्किल अल्पविराम ऑपरेटर ... जब एक अल्पविराम अल्पविराम नहीं होता है। अल्पविराम ऑपरेटर के कोष्ठक और दुर्लभता ने मुझे फेंक दिया। कोई बात नहीं!

4

पीडीपी -11 ने इंस्ट्रक्शन सेट में पोस्ट-इन्क्रीमेंट और प्री-डिक्रीमेंट ऑपरेशंस की पेशकश की। अब ये निर्देश नहीं थे। वे अनुदेश संशोधक थे जो आपको यह निर्दिष्ट करने की अनुमति देते थे कि आप एक रजिस्टर का मूल्य चाहते थे, इससे पहले कि यह बढ़ा हुआ था या इसके घटने के बाद था।

यहाँ मशीन भाषा में एक शब्द-प्रतिलिपि कदम है:

movw (r1)++,(r2)++

जो रजिस्टरों द्वारा इंगित किए गए एक स्थान से दूसरे स्थान पर एक शब्द ले गया, और रजिस्टरों को फिर से करने के लिए तैयार होगा।

जैसा कि C पर बनाया गया था और PDP-11 के लिए, बहुत सी उपयोगी अवधारणाओं को सी। सी में अपना रास्ता मिल गया था, जिसका उद्देश्य कोडांतरक भाषा के लिए एक उपयोगी प्रतिस्थापन होना था। समरूपता के लिए पूर्व वेतन वृद्धि और पश्चात वेतन वृद्धि को जोड़ा गया था।


यह शानदार संशोधक है ... यह मुझे पीडीपी -11 विधानसभा सीखना चाहता है। BTW, क्या आपके पास "समरूपता के लिए" पर एक संदर्भ है? यह समझ में आता है, लेकिन यह इतिहास है, कभी-कभी यह समझ में आता है कि कुंजी नहीं थी। LOL
बेनपेन

2
जिन्हें संबोधित करने के तरीके के रूप में भी जाना जाता है । पीडीपी -11 ने पोस्ट-इन्क्रीमेंट और प्री-डिक्रीमेंट प्रदान किया जो स्टैक ऑपरेशन्स के लिए एक साथ जोड़े थे।
एरिक इद्दत

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

3
क्षमा करें, PDP-11 ने इन ऑपरेटरों को प्रेरित नहीं किया। यह अभी तक मौजूद नहीं था जब केन थॉम्पसन ने उनका आविष्कार किया था। मेरा जवाब देखिए ।
कीथ थॉम्पसन

3

मुझे संदेह है कि यह वास्तव में आवश्यक था। जहाँ तक मुझे पता है, यह लूप में, पूर्व-वेतन वृद्धि का उपयोग करने की तुलना में अधिकांश प्लेटफार्मों पर अधिक कॉम्पैक्ट में कुछ भी संकलित नहीं करता है। यह सिर्फ इतना था कि जिस समय यह बनाया गया था, कोड की स्पष्टता की तुलना में कोड की मर्यादा अधिक महत्वपूर्ण थी।

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

यह & & | की तरह है ऑपरेटर == की तुलना में कम वरीयता वाला है

यह सबसे अच्छे इरादों (&& और; का एक गैर-लघु परिचालित संस्करण) के साथ डिज़ाइन किया गया था, लेकिन अब यह प्रोग्रामर को हर रोज भ्रमित करता है, और यह शायद कभी नहीं बदलेगा।

वैसे भी, यह केवल इस बात का उत्तर है कि मुझे लगता है कि आपके प्रश्न का कोई अच्छा उत्तर नहीं है, लेकिन मैं शायद पहले से अधिक गुरु कोडर द्वारा गलत साबित हो जाऊंगा।

--EDIT--

मुझे ध्यान देना चाहिए कि मुझे अविश्वसनीय रूप से उपयोगी दोनों मिल रहे हैं, मैं सिर्फ इशारा कर रहा हूं कि यह नहीं बदलेगा कि कोई इसे पसंद करता है या नहीं।


यह भी दूर से सच नहीं है। किसी भी बिंदु पर स्पष्टता की तुलना में "कोड की मर्यादा" अधिक महत्वपूर्ण नहीं थी।
कोड़ी ग्रे

ठीक है, मैं तर्क दूंगा कि यह एक बिंदु पर केंद्रित था। आप काफी सही हैं, हालांकि, यह निश्चित रूप से कोड की स्पष्टता ... ज्यादातर लोगों के लिए अधिक महत्वपूर्ण नहीं है ।

6
ठीक है, "terse" की परिभाषा "सुचारू रूप से सुरुचिपूर्ण: पॉलिश" या "कुछ शब्दों का उपयोग करके: अतिशयोक्ति से रहित है," दोनों आमतौर पर कोड लिखते समय एक अच्छी बात है। "ट्रिक" का अर्थ यह नहीं है कि "अस्पष्ट, पढ़ने में कठिन और मोटे तौर पर" जैसे कई लोग सोचते हैं।
जेम्स मैकनेलिस

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

1
४० साल पीछे हटें और कल्पना करें कि आपको अपने कार्यक्रम को उस ड्रम पर फिट करना था जो केवल १००० पात्रों को धारण करेगा, या एक कंपाइलर लिखकर केवल ४ हजार बाइट्स के साथ काम कर सकता है। ऐसे समय थे जहां स्पष्टता बनाम स्पष्टता भी एक मुद्दा नहीं था। आपको इस पद पर रहना पड़ता था, इस ग्रह पर एक ऐसा कंप्यूटर मौजूद नहीं था जो आपके गैर-प्रोग्राम प्रोग्राम को स्टोर, रन या संकलित कर सके।
नं

3

मुझे पॉइंटर्स के साथ काम करते समय पोस्टफ़ेयर अपर्चर पसंद है (क्योंकि मैं उन्हें डिफरेंस कर रहा हूं या नहीं) क्योंकि

p++

बराबर की तुलना में "अगले स्थान पर जाने" के रूप में अधिक स्वाभाविक रूप से पढ़ता है

p += 1

जो निश्चित रूप से शुरुआती को भ्रमित करना चाहते हैं वे पहली बार इसे एक पॉइंटर के साथ उपयोग करते हुए देखते हैं जहां आकार (* पी)! = 1।

क्या आप वाकई भ्रम की समस्या को सही ढंग से बता रहे हैं? क्या वह चीज नहीं है जो इस तथ्य को भ्रमित करती है कि पोस्टफिक्स ++ ऑपरेटर के पास डिरेलमेंट * ऑपरेटर की तुलना में अधिक पूर्वता है, ताकि

*p++

के रूप में पर्स

*(p++)

और नहीं

(*p)++

जैसा कि कुछ उम्मीद कर सकते हैं?

(आपको लगता है कि यह बुरा है। देखें सी घोषणाएं पढ़ना ।)


2

अच्छी प्रोग्रामिंग के सूक्ष्म तत्वों में स्थानीयकरण और अतिसूक्ष्मवाद हैं :

  • उपयोग के न्यूनतम दायरे में चर डालते हुए
  • लिखने का उपयोग करने के लिए कास्ट का उपयोग करना आवश्यक नहीं है
  • आदि।

उसी भावना में, तुरंत x++वर्तमान मूल्य का संदर्भ देने के एक तरीके के रूप में देखा जा सकता है , xजबकि यह दर्शाता है कि आप कम से कम अभी के लिए - उस मूल्य के साथ समाप्त हो गए हैं और अगले (वैध xहै intया नहीं ) के लिए आगे बढ़ना चाहते हैं एक सूचक या पुनरावृत्त)। थोड़ी कल्पना के साथ, आप इसकी तुलना पुराने मूल्य / स्थिति को x"कार्यक्षेत्र से बाहर" करने के तुरंत बाद कर सकते हैं, क्योंकि इसकी अब आवश्यकता नहीं है, और नए मूल्य पर जा रहे हैं। सटीक बिंदु जहां संक्रमण संभव है, उपसर्ग द्वारा हाइलाइट किया गया है++ । निहितार्थ यह है कि यह संभवतः "पुराने" का अंतिम उपयोग xएल्गोरिदम में मूल्यवान अंतर्दृष्टि हो सकता है, प्रोग्रामर की सहायता करता है क्योंकि वे आसपास के कोड के माध्यम से स्कैन करते हैं। बेशक, पोस्टफिक्स++ नए मान के उपयोग के लिए प्रोग्रामर को खोज पर रख सकता है, जो कि नए मूल्य वास्तव में आवश्यक होने के आधार पर अच्छा नहीं हो सकता है या नहीं, इसलिए यह प्रोग्रामिंग के "कला" या "शिल्प" का एक पहलू है जो यह निर्धारित करता है कि क्या अधिक है परिस्थितियों में सहायक।

हालांकि कई शुरुआती एक विशेषता से भ्रमित हो सकते हैं, यह संतुलन के लायक है कि दीर्घकालिक लाभ के खिलाफ: शुरुआती शुरुआती लंबे समय तक नहीं रहते हैं।


2

वाह, बहुत सारे जवाब नहीं-ऑन-पॉइंट (अगर मैं इतना बोल्ड हो सकता हूं), और कृपया मुझे माफ कर दें अगर मैं स्पष्ट इंगित कर रहा हूं - विशेष रूप से आपकी टिप्पणी के प्रकाश में, शब्दार्थ को इंगित नहीं करने के लिए, लेकिन स्पष्ट (स्ट्रॉस्ट्रुप के दृष्टिकोण से, मुझे लगता है) अभी तक पोस्ट नहीं किया गया लगता है! :)

पोस्टफ़िक्स x++एक अस्थायी पैदा करता है जो अभिव्यक्ति में 'ऊपर की ओर' गुजरता है, जबकि चर xबाद में बढ़ जाता है।

उपसर्ग ++xएक अस्थायी वस्तु का उत्पादन नहीं करता है, लेकिन 'x' वेतन वृद्धि करता है और परिणाम को अभिव्यक्ति में बदल देता है।

मूल्य सुविधा है, उन लोगों के लिए जो ऑपरेटर जानते हैं।

उदाहरण के लिए:

int x = 1;
foo(x++); // == foo(1)
// x == 2: true

x = 1;
foo(++x); // == foo(2)
// x == 2: true

बेशक, इस उदाहरण के परिणाम अन्य समकक्ष (और शायद कम तिरछा) कोड से उत्पादित किए जा सकते हैं।

तो हमारे पास पोस्टफिक्स ऑपरेटर क्यों है? मुझे लगता है क्योंकि यह एक मुहावरा है जो कायम है, भ्रम के बावजूद यह स्पष्ट रूप से बनाता है। यह एक विरासत का निर्माण है जो एक बार मूल्य के लिए माना जाता था, हालांकि मुझे यकीन नहीं है कि सुविधा के लिए प्रदर्शन के लिए कथित मूल्य इतना था। वह सुविधा नहीं खोई है, लेकिन मुझे लगता है कि पठनीयता की सराहना बढ़ी है, जिसके परिणामस्वरूप ऑपरेटर के उद्देश्य पर सवाल उठाया गया है।

क्या हमें अब पोस्टफिक्स ऑपरेटर की आवश्यकता है? शायद नहीं। इसका परिणाम भ्रामक है और समझने में अवरोध पैदा करता है। कुछ अच्छे कोडर्स निश्चित रूप से तुरंत जान पाएंगे कि इसे कहां उपयोगी पाया जाए, अक्सर उन जगहों पर जहां इसकी ख़ासियत "पर्कल-एस्के" सौंदर्य है। उस सुंदरता की लागत पठनीयता है।

मैं सहमत हूं कि स्पष्ट संहिता में पठनीयता, समझ और स्थिरता में लाभ है। अच्छे डिजाइनर और प्रबंधक चाहते हैं कि।

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

दूसरे शब्दों में, कुछ लोगों while (*dst++ = *src++);को बस एक और अधिक सुंदर समाधान लगता है, कुछ ऐसा जो आपकी सांस को अपनी सादगी से दूर ले जाता है, जैसे कि यह कैनवास के लिए एक ब्रश था। यह कि आप भाषा को समझने के लिए मजबूर हैं कि सुंदरता की सराहना केवल इसकी भव्यता में ही होती है।


3
+1 "कुछ लोग पाते हैं (* dst ++ = * src ++), बस एक और सुंदर समाधान बनने के लिए"। निश्चित रूप से। जो लोग असेंबली लैंग्वेज को नहीं समझते हैं, वे वास्तव में यह नहीं समझ पाते हैं कि सी कितना एलिगेंट हो सकता है, लेकिन यह विशेष कोड स्टेटमेंट एक चमकता सितारा है।
टिन मैन

"क्या हमें अब पोस्टफिक्स ऑपरेटर की आवश्यकता है? संभवतः नहीं।" - मैं यहाँ ट्यूरिंग मशीनों के बारे में सोचने में मदद नहीं कर सकता। क्या हमें कभी भी स्वचालित चर की आवश्यकता है, forबयान, बिल्ली, यहां तक ​​कि while(हमारे पास goto, आखिरकार)?

@ बियर: हा! बंद कल्पना करो! बंद! परिवादात्मक! lol
ब्रायन एम। हंट

बंद! बेहद बेहूदा। बस मुझे एक टेप दे दो! सच में, मेरा मतलब यह है कि मुझे नहीं लगता / जरूरत है / एक विशेषता प्राथमिक निर्णय मानदंड होना चाहिए (जब तक आप डिजाइन करना चाहते हैं, कहते हैं, लिस्प)। IME I (nay, need ) का उपयोग पोस्टफिक्स ऑपरेटर्स लगभग विशेष रूप से करते हैं, और इसके बजाय केवल शायद ही कभी उपसर्ग की आवश्यकता होती है।

2

आइए Kernighan & Ritchie के मूल औचित्य (मूल K & R पृष्ठ 42 और 43) को देखें:

असामान्य पहलू यह है कि ++ और - का उपयोग उपसर्ग के रूप में या उपसर्ग के रूप में किया जा सकता है। (...) उस संदर्भ में जहां कोई मूल्य नहीं है (..) स्वाद के अनुसार उपसर्ग या उपसर्ग चुनें। लेकिन हेरे ऐसी स्थितियां हैं जिनमें एक या दूसरे को विशेष रूप से बुलाया जाता है।

पाठ कुछ उदाहरणों के साथ जारी है जो सूचकांक के भीतर वृद्धि का उपयोग करते हैं, " अधिक कॉम्पैक्ट " कोड लिखने के स्पष्ट लक्ष्य के साथ । तो इन ऑपरेटरों के पीछे कारण अधिक कॉम्पैक्ट कोड की सुविधा है।

तीन उदाहरण दिए गए ( squeeze(), getline()और strcat()) अनुक्रमण का उपयोग कर भाव भीतर केवल पोस्टफ़िक्स का उपयोग करें। लेखक कोड की तुलना एक लंबे संस्करण से करते हैं जो एम्बेडेड वेतन वृद्धि का उपयोग नहीं करता है। यह पुष्टि करता है कि ध्यान कॉम्पैक्टनेस पर है।

पृष्ठ 102 पर K & R हाइलाइट, पॉइंटर डेरेफ़रिंग (जैसे *--pऔर *p--) के साथ संयोजन में इन ऑपरेटरों का उपयोग । आगे कोई उदाहरण नहीं दिया गया है, लेकिन फिर, वे स्पष्ट करते हैं कि लाभ कॉम्पैक्ट है।

उदाहरण के लिए उपसर्ग बहुत आम तौर पर उपयोग किया जाता है जब एक सूचकांक या एक सूचक को अंत से घूरते हुए।

 int i=0; 
 while (i<10) 
     doit (i++);  // calls function for 0 to 9  
                  // i is 10 at this stage
 while (--i >=0) 
     doit (i);    // calls function from 9 to 0 

1

मैं इस आधार से असहमत होने जा रहा हूं कि ++p, p++किसी तरह से पढ़ना या अस्पष्ट होना मुश्किल है। एक का अर्थ है "वेतन वृद्धि पी और फिर पी पढ़ें", दूसरे का अर्थ है "पढ़ा हुआ पी और फिर वेतन वृद्धि पी"। दोनों मामलों में, कोड में ऑपरेटर बिल्कुल वही है जहां यह कोड के स्पष्टीकरण में है, इसलिए यदि आप जानते हैं कि ++इसका क्या मतलब है, तो आपको पता है कि परिणामी कोड का क्या अर्थ है।

आप किसी भी सिंटैक्स का उपयोग करके ओफ़्फ़ुसेटेड कोड बना सकते हैं , लेकिन मुझे यहाँ ऐसा कोई मामला नहीं दिखता है p++/ ++pजो स्वाभाविक रूप से ऑब्सफ़ैक्टरी हो।


1

यह एक इलेक्ट्रिकल इंजीनियर के POV से है:

कई प्रोसेसर हैं जो एक अंतिम-प्रथम-आउट (एलआईएफओ) स्टैक को बनाए रखने के उद्देश्य से अंतर्निहित पोस्ट-इन्क्रीमेंट और पूर्व-डिक्रीमेंट ऑपरेटर हैं।

यह इस तरह हो सकता है:

 float stack[4096];
 int stack_pointer = 0;

 ... 

 #define push_stack(arg) stack[stack_pointer++] = arg;
 #define pop_stack(arg) arg = stack[--stack_pointer];

 ...

मुझे पता नहीं है, लेकिन यही कारण है कि मैं उपसर्ग और पश्चगामी वेतन वृद्धि ऑपरेटरों को देखने की उम्मीद करूंगा।


1

कॉम्पैक्टनेस के बारे में क्रिस्टोफ की बात को रेखांकित करने के लिए, मैं V6 से कुछ कोड y'all दिखाना चाहता हूं। यह मूल सी कंपाइलर का हिस्सा है, http://minnie.tuhs.org/cgi-bin/utree.pl?file=V6/usr/source/c/c00.c से :

/*
 * Look up the identifier in symbuf in the symbol table.
 * If it hashes to the same spot as a keyword, try the keyword table
 * first.  An initial "." is ignored in the hash.
 * Return is a ptr to the symbol table entry.
 */
lookup()
{
    int ihash;
    register struct hshtab *rp;
    register char *sp, *np;

    ihash = 0;
    sp = symbuf;
    if (*sp=='.')
        sp++;
    while (sp<symbuf+ncps)
        ihash =+ *sp++;
    rp = &hshtab[ihash%hshsiz];
    if (rp->hflag&FKEYW)
        if (findkw())
            return(KEYW);
    while (*(np = rp->name)) {
        for (sp=symbuf; sp<symbuf+ncps;)
            if (*np++ != *sp++)
                goto no;
        csym = rp;
        return(NAME);
    no:
        if (++rp >= &hshtab[hshsiz])
            rp = hshtab;
    }
    if(++hshused >= hshsiz) {
        error("Symbol table overflow");
        exit(1);
    }
    rp->hclass = 0;
    rp->htype = 0;
    rp->hoffset = 0;
    rp->dimp = 0;
    rp->hflag =| xdflg;
    sp = symbuf;
    for (np=rp->name; sp<symbuf+ncps;)
        *np++ = *sp++;
    csym = rp;
    return(NAME);
}

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

इसका एक हिस्सा निश्चित रूप से उस प्रकार का माइक्रो-ऑप्टिमाइजेशन था, जिसकी उम्मीद है कि कंपाइलर आज हमारे लिए क्या करेंगे, लेकिन मैं इस परिकल्पना को भी आगे रखूंगा कि जब कंप्यूटर में आपका पूरा इंटरफेस एक सिंगल 80x25 ग्लास ट्टी हो, तो आप अपना कोड चाहते हैं। जितना संभव हो उतना घना होना ताकि आप एक ही समय में अधिक देख सकें।

(सब कुछ के लिए वैश्विक बफ़र्स का उपयोग संभवतः असेंबली भाषा पर किसी के दांत काटने से हैंगओवर है।)


देखभाल के साथ संभाल: "ihash = + * sp ++;" कुछ बिंदु पर C के पास न केवल + = बल्कि ऑपरेटर भी था। आज, = + एक असाइनमेंट ऑपरेटर है, इसके बाद एक यूनीरी प्लस जो कुछ भी नहीं करता है, इसलिए यह "ihash = * sp; sp + = 1;" के बराबर है।
gnasher729

@ gnasher729 हाँ, और बाद में यह है rp->hflag =| xdflg, जो मुझे लगता है कि एक आधुनिक संकलक पर एक वाक्यविन्यास त्रुटि होगी। "कुछ बिंदु पर" ठीक वी 6 है, जैसा कि ऐसा होता है; +=V7 में खुश करने के लिए बदलाव (V6 कंपाइलर केवल स्वीकार किए जाते हैं =+, अगर मैं इस कोड को सही ढंग से पढ़ रहा हूं - एक ही फ़ाइल में प्रतीक () देखें।)
zwol

-1

शायद आपको कॉस्मेटिक्स के बारे में भी सोचना चाहिए।

while( i++ )

यकीनन "इससे बेहतर" दिखता है

while( i+=1 )

किसी कारण से, पोस्ट-इन्क्रीमेंट ऑपरेटर बहुत आकर्षक लग रहा है। इसकी छोटी, इसकी मीठी, और यह सब कुछ 1 से बढ़ाती है। इसकी तुलना उपसर्ग से करें:

while( ++i )

"पीछे दिखता है" यह नहीं है? आप कभी भी गणित में एक प्लस साइन FIRST को नहीं देखते हैं, सिवाय इसके कि जब किसी के कुछ सकारात्मक ( +0या ऐसा कुछ) निर्दिष्ट करने के साथ मूर्खतापूर्ण हो । हमें OBJECT + SOMETHING देखने की आदत है

यह ग्रेडिंग के साथ कुछ करना है? ए, ए +, ए ++? मैं आपको बता सकता हूँ कि मैं पहले बहुत खुश था कि पायथन लोगों operator++को उनकी भाषा से हटा दिया गया था!


1
आपके उदाहरण एक ही काम नहीं करते हैं। i++के मूल मान देता है i, और i+=1और ++iके मूल मान iप्लस 1. आप इस मामले को नियंत्रण प्रवाह के लिए बदले मानों का उपयोग कर रहे हैं,।
डेविड थॉर्नले

हाँ तुम सही हो। लेकिन मैं यहाँ केवल पठनीयता देख रहा हूँ।
बोबोबोबो

-2

पीछे की ओर 9 से 0 समावेशी गणना:

for (unsigned int i=10; i-- > 0;)  {
    cout << i << " ";
}

या लूप के बराबर है।


1
कैसे के बारे में for (unsigned i = 9; i <= 9; --i)?
fredoverflow
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.