paint-brush
Muhtemelen Bilmediğiniz C ve C++'ın Gizli Hazineleriile@udalov
11,231 okumalar
11,231 okumalar

Muhtemelen Bilmediğiniz C ve C++'ın Gizli Hazineleri

ile Ilia6m2024/08/09
Read on Terminal Reader

Çok uzun; Okumak

C++ çok fazla özelliği olan harika bir dildir. Bir C++ geliştiricisi olarak kariyerim boyunca birçok "WTF" anı yaşadım. Bu hikayede, C ve C++ programlamanın en eğlenceli yönlerini testler biçiminde yoğunlaştırılmış olarak bulacaksınız. Birkaç sorudan fazlasını doğru yanıtlamanız mümkün değil.
featured image - Muhtemelen Bilmediğiniz C ve C++'ın Gizli Hazineleri
Ilia HackerNoon profile picture
0-item
1-item

Programlamanın C ve C++'ın görkemli dünyasına katılmaya hazır mısınız? Birkaç basit C++ satırından sonra varlığınızı sorgulamak ister misiniz?


Cevabınız "Evet!", "Evet" veya "Neden olmasın?" ise - bilginizi test etmeye hoş geldiniz. C veya C++ ile ilgili birden fazla soru sorulacaktır.


Doğru cevapları ve açıklamaları hikayenin sonunda bulabilirsiniz. İyi şanslar!

1. En küçük program

 main;


Bu programı C derleyicisini kullanarak derlemeye çalışırsanız ne olur?

  1. derlenmeyecek
  2. derlenecek, bağlanmayacak
  3. derleyecek ve bağlayacak

2. Çatal

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


Bu program kaç satır yazdıracak?

  1. 1000
  2. 1000'den az
  3. 1000'den fazla

3. İhtiyacınız olan tek şey endeksler

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


Bu program ne yazdıracak?

  1. 1
  2. 2
  3. 3
  4. 4
  5. derlenmeyecek
  6. tanımlanmamış

4. Düzenli ifadeler

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


Bu düzenli ifadenin bu girdi dizesiyle eşleşmesi ne kadar zaman alacak?


  1. 1 ms
  2. 1 saniye
  3. 1 dk
  4. 1 saat
  5. 1 yıl
  6. sonsuza kadar

5. Hareketler ve lambdalar

 #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; }


Bu program tarafından yazdırılacak son satır…


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

6. X ve çubuk

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


Bu program ne yazdıracak?

  1. 0
  2. 1
  3. 0x0
  4. derlenmeyecek
  5. Bağlantı olmayacak

7. Yapıcılar

 #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(); }


Bu program tarafından yazdırılacak son satır…

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

Sonuç yerine

Umarım bu tuhaf parçalardan birini doğada asla bulamazsınız.

Cevaplar

  1. En küçük program


    Bu yasal bir C kodudur. Derlenecek ve başarıyla bağlanacaktır. Çalıştırmaya çalışırsanız çökecektir. main; - global değişkendir.


    C kodunda birçok şeyi atlayabilirsiniz. Örneğin, global bir değişkenin türünü atlayabilirsiniz. Varsayılan olarak derleyici bu türün bir int olduğunu varsayacaktır. Ayrıca C'de isim karıştırma yoktur (C++'ın aksine), bu yüzden bağlantı yaparken değişken main fonksiyon main ayırmanın bir yolu yoktur.


    Böylece derleyici geçerli kodu derleyecek ve bağlayıcı, programı bağlamak için nesne dosyasında main adında bir şey bulacaktır.


  2. Çatal


    Bu, C veya C++ özelliğinden ziyade daha çok POSIX özelliğidir. IO işlemlerinin uygulamaları performansı optimize etmek için tamponları kullanır. fork çağırdığınızda, işletim sistemi işlem belleğinin yazma sırasında kopyasını oluşturur, IO tamponları da muhtemelen kopyalanır ve tamponlanmış dizeler muhtemelen 1000'den fazla kez yazdırılır .


  3. İhtiyacınız olan tek şey endeksler


    Cevap 3'tür


    Bu kodu anlamak için C ve C++'da dizinlerin nasıl çalıştığına daha yakından bakalım: array[index] , *(array + index) ile aynıdır, (index + array) ile aynıdır ve index[array ] ile aynıdır.

    İkinci ipucu ise operatör , 'dir. İkili operatörüdür, sol argümanı atar ve sağ argümanı döndürür.


  4. Düzenli ifadeler


    Ne olacağını tahmin etmek imkansız ! Davranış uygulamaya bağlıdır.


    Benim çevremde bu program The complexity of an attempted match against a regular expression exceeded a pre-set level.


    Diğer olası seçenekler şaşırtıcı derecede uzun zaman veya beklendiği gibi çalışmaktır. Bunun nedeni, düzenli ifadeleri uygulamak için iki olası yaklaşım olmasıdır.


    İlk olarak - düzenli ifadeleri sonlu otomatlara dönüştürün O(n**2) (n - desen uzunluğu), dizeyi eşleştirin O(m) (m - dize uzunluğu). Bu yaklaşım geri izlemeyi desteklemez.


    İkincisi - açgözlü yaklaşım + DFS, geri izlemeyi destekler ancak belirli desenlerde üstel zaman karmaşıklığına eğilimlidir.


  5. Hareketler ve lambdalar


    Cevap Foo(const Foo&) 'dur. Lambdalar varsayılan olarak değişmezdir, lambdaya [] ile yakalanan tüm değerler örtük olarak const . Bu, lambdalar için idempotent davranışı açar.


    f hareket ettirdiğinizde const Foo&& oluşturursunuz. const Foo&& garip bir türdür, bu nedenle derleyici sadece Foo kopyalar


    Bunu düzeltmenin iki yolu vardır:


    1. Değişken lambda oluştur

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


    2. Foo(const Foo&&) yapıcısını bildirin


  6. X ve çubuk

    Program 1 değerini yazdıracaktır.


    int bar(int(x)); — fonksiyonu bildirmenin garip bir yoludur, int bar(int x); ile aynıdır.

    Eğer tip dönüşümü ile karıştırdıysanız, int bar((int(x))); - bu bir tip dönüşümüdür.


    Daha sonra address fonksiyonunu dolaylı olarak bool türüne dönüştürmeye çalışırız, böyle bir dönüştürmenin sonucu her zaman true olur.


    bar() fonksiyonu hiç kullanılmadı, bu sayede bağlantı sırasında referans alınmayan sembol hatalarından kaçınabiliyoruz.


  7. Yapıcılar

    Son satır Foo(const Foo&, int) şeklindedir.


    Foo(i) , Foo i ile aynı olan değişken bildirimidir. Bu nedenle, i adlı sınıf üyesi bu kapsamda gizlidir.