paint-brush
C और C++ के छुपे हुए रत्न जो शायद आप नहीं जानतेद्वारा@udalov
11,231 रीडिंग
11,231 रीडिंग

C और C++ के छुपे हुए रत्न जो शायद आप नहीं जानते

द्वारा Ilia6m2024/08/09
Read on Terminal Reader

बहुत लंबा; पढ़ने के लिए

C++ एक बेहतरीन भाषा है जिसमें बहुत सारी खूबियाँ हैं। C++ डेवलपर के रूप में अपने करियर के दौरान मैंने कई "WTF" पलों का अनुभव किया है। इस कहानी में, आपको C और C++ प्रोग्रामिंग के सबसे मनोरंजक पहलुओं को परीक्षणों के रूप में संक्षेपित किया जाएगा। ऐसा कोई तरीका नहीं है जिससे आप एक-दो से ज़्यादा सवालों के सही जवाब दे सकें।
featured image - C और C++ के छुपे हुए रत्न जो शायद आप नहीं जानते
Ilia HackerNoon profile picture
0-item
1-item

क्या आप प्रोग्रामिंग के C और C++ की शानदार दुनिया में शामिल होने के लिए तैयार हैं? क्या आप C++ की कुछ सरल पंक्तियों के बाद अपने अस्तित्व पर सवाल उठाना चाहते हैं?


यदि आपका उत्तर "हाँ!", "हाँ" या "क्यों नहीं?" है - तो अपने ज्ञान का परीक्षण करने के लिए आपका स्वागत है। आपको C या C++ से संबंधित कई प्रश्न दिए जाएँगे।


कृपया कहानी के अंत में सही उत्तर और स्पष्टीकरण पाएँ। शुभकामनाएँ!

1. सबसे छोटा कार्यक्रम

 main;


यदि आप इस प्रोग्राम को C कम्पाइलर का उपयोग करके संकलित करने का प्रयास करेंगे तो क्या होगा?

  1. संकलित नहीं होगा
  2. संकलित होगा, लिंक नहीं होगा
  3. संकलित करेगा और लिंक करेगा

2. कांटा

 #include <iostream> #include <unistd.h> int main() { for(auto i = 0; i < 1000; i++) std::cout << "Hello world!\n"; fork(); }


यह प्रोग्राम कितनी लाइनें प्रिंट करेगा?

  1. 1000
  2. 1000 से कम
  3. 1000 से अधिक

3. आपको बस सूचकांक की जरूरत है

 #include <iostream> int main() { int array[] = { 1, 2, 3 }; std::cout << (4, (1, 2)[array]) << std::endl; }


यह प्रोग्राम क्या प्रिंट करेगा?

  1. 1
  2. 2
  3. 3
  4. 4
  5. संकलित नहीं होगा
  6. अपरिभाषित

4. नियमित अभिव्यक्ति

 #include <regex> #include <iostream> int main() { std::regex re("(.*|.*)*O"); std::string str("0123456789"); std::cout << std::regex_match(str, re); return 0; }


इस नियमित अभिव्यक्ति को इस इनपुट स्ट्रिंग से मेल खाने में कितना समय लगेगा?


  1. 1 मि.से.
  2. 1 सेकंड
  3. 1 मिनट
  4. 1 घंटा
  5. 1 वर्ष
  6. हमेशा के लिए

5. चालें और लैम्ब्डा

 #include <iostream> struct Foo { Foo() { std::cout << "Foo()\n"; } Foo(Foo&&) { std::cout << "Foo(Foo&&)\n"; } Foo(const Foo&) { std::cout << "Foo(const Foo&)\n"; } }; int main() { Foo f; auto a = [f = std::move(f)]() { return std::move(f); }; Foo f2(a()); return 0; }


इस प्रोग्राम द्वारा मुद्रित की जाने वाली अंतिम पंक्ति है...


  1. Foo()
  2. Foo(Foo&&)
  3. Foo(const Foo&)

6. एक्स और बार

 #include <iostream> int x = 0; int bar(int(x)); int main() { std::cout << bar; }


यह प्रोग्राम क्या प्रिंट करेगा?

  1. 0
  2. 1
  3. 0x0
  4. संकलित नहीं होगा
  5. लिंक नहीं होगा

7. कंस्ट्रक्टर्स

 #include <iostream> struct Foo { Foo() { std::cout << "Foo()\n"; } Foo(const Foo&) { std::cout << "Foo(const Foo&)\n"; } Foo(int) { std::cout << "Foo(int)\n"; } Foo(int, int) { std::cout << "Foo(int, int)\n"; } Foo(const Foo&, int) { std::cout << "Foo(const Foo&, int)\n"; } Foo(int, const Foo&) { std::cout << "Foo(int, const Foo&)\n"; } }; void f(Foo) {} struct Bar { int i, j; Bar() { f(Foo(i, j)); f(Foo(i)); Foo(i, j); Foo(i); Foo(i, j); } }; int main() { Bar(); }


इस प्रोग्राम द्वारा मुद्रित की जाने वाली अंतिम पंक्ति है...

  1. Foo(int, int)
  2. Foo(const Foo&, int)
  3. Foo(int, const Foo&)
  4. Foo(int)

निष्कर्ष के बजाय

मुझे आशा है कि आपको जंगल में इस तरह का कोई विचित्र टुकड़ा कभी नहीं मिलेगा।

जवाब

  1. सबसे छोटा कार्यक्रम


    यह वैध C कोड है। यह सफलतापूर्वक संकलित और लिंक होगा। यदि आप इसे चलाने का प्रयास करेंगे तो यह क्रैश हो जाएगा। main; - वैश्विक चर है।


    सी कोड में आप बहुत सी चीजों को छोड़ सकते हैं। उदाहरण के लिए आप किसी ग्लोबल वैरिएबल के प्रकार को छोड़ सकते हैं। डिफ़ॉल्ट रूप से कंपाइलर यह मान लेगा कि यह प्रकार int है। साथ ही सी में कोई नाम मैन्गलिंग नहीं है (सी++ के विपरीत), इसलिए लिंक करते समय वैरिएबल main फ़ंक्शन main से अलग करने का कोई तरीका नहीं है।


    इस प्रकार कंपाइलर वैध कोड संकलित करेगा, और लिंकर प्रोग्राम को लिंक करने के लिए ऑब्जेक्ट फ़ाइल में main नाम की कोई चीज़ ढूंढेगा।


  2. कांटा


    यह C या C++ फीचर की बजाय POSIX फीचर है। IO ऑपरेशन के कार्यान्वयन प्रदर्शन को अनुकूलित करने के लिए बफ़र्स का उपयोग करते हैं। जब आप fork आह्वान करते हैं, तो OS प्रक्रिया मेमोरी की कॉपी-ऑन-राइट डुप्लिकेट बनाएगा, IO-बफ़र्स भी संभवतः डुप्लिकेट होंगे और बफ़र किए गए स्ट्रिंग्स संभवतः 1000 से अधिक बार प्रिंट किए जाएंगे


  3. आपको बस सूचकांक की जरूरत है


    उत्तर 3 है


    इस कोड को समझने के लिए आइए देखें कि C और C++ में इंडेक्स कैसे काम करते हैं: array[index] , *(array + index) के समान है, (index + array) के समान है और index[array .

    दूसरा सुराग ऑपरेटर है , इसका बाइनरी ऑपरेटर, यह बाएं तर्क को त्याग देता है और दाएं तर्क को वापस करता है।


  4. नियमित अभिव्यक्ति


    यह भविष्यवाणी करना असंभव है कि क्या होगा! व्यवहार कार्यान्वयन पर निर्भर है।


    मेरे परिवेश में यह प्रोग्राम अपवाद उत्पन्न करता है The complexity of an attempted match against a regular expression exceeded a pre-set level.


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


    पहला - नियमित अभिव्यक्तियों को परिमित ऑटोमेटा O(n**2) (n - पैटर्न की लंबाई) में बदलें, स्ट्रिंग O(m) (m - स्ट्रिंग की लंबाई) से मिलान करें। यह दृष्टिकोण बैकट्रैकिंग का समर्थन नहीं करता है।


    दूसरा - लालची दृष्टिकोण + DFS, बैकट्रैकिंग का समर्थन करता है लेकिन कुछ पैटर्न पर घातीय समय जटिलता के लिए प्रवण है।


  5. चालें और लैम्ब्डा


    उत्तर है Foo(const Foo&) । लैम्ब्डा डिफ़ॉल्ट रूप से अपरिवर्तनीय होते हैं, [] के साथ लैम्ब्डा में कैप्चर किए गए सभी मान अंतर्निहित रूप से const होते हैं। यह लैम्ब्डा के लिए idempotent व्यवहार को अनलॉक करता है।


    जब आप f स्थानांतरित करते हैं तो आप const Foo&& बनाते हैं। const Foo&& एक अजीब प्रकार है, इसलिए कंपाइलर बस Foo प्रतिलिपि बनाता है


    इसे ठीक करने के दो तरीके हैं:


    1. परिवर्तनीय लैम्ब्डा बनाएं

       auto a = [f = std::move(f)]() mutable { return std::move(f); };


    2. कन्स्ट्रक्टर Foo(const Foo&&) घोषित करें


  6. एक्स और बार

    प्रोग्राम 1 प्रिंट करेगा.


    int bar(int(x)); — फ़ंक्शन घोषित करने का अजीब तरीका है, यह int bar(int x); के बराबर है।

    यदि आप टाइप कास्ट से भ्रमित हैं, int bar((int(x))); - यह टाइप कास्ट है।


    फिर हम फ़ंक्शन पते को bool में निहित रूप से डालने का प्रयास करते हैं, ऐसे डालने का परिणाम हमेशा true है।


    फ़ंक्शन bar() कभी भी उपयोग नहीं किया गया है, जो हमें लिंक करते समय अप्रतिबंधित प्रतीक त्रुटि से बचने की अनुमति देता है।


  7. कंस्ट्रक्टर्स

    अंतिम पंक्ति Foo(const Foo&, int) है।


    Foo(i) एक चर घोषणा है, जो Foo i के समान है। इस प्रकार i नाम के अंतर्गत वर्ग सदस्य इस दायरे में छिपा हुआ है।