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?
- derlenmeyecek
- derlenecek, bağlanmayacak
- 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?
- 1000
- 1000'den az
- 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
- 2
- 3
- 4
- derlenmeyecek
- 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 ms
- 1 saniye
- 1 dk
- 1 saat
- 1 yıl
- 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…
-
Foo()
-
Foo(Foo&&)
-
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?
-
0
-
1
-
0x0
- derlenmeyecek
- 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…
-
Foo(int, int)
-
Foo(const Foo&, int)
-
Foo(int, const Foo&)
-
Foo(int)
Sonuç yerine
Umarım bu tuhaf parçalardan birini doğada asla bulamazsınız.
Cevaplar
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şkenmain
fonksiyonmain
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.
Ç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 .
İ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 veindex[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.
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ştirinO(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.
Hareketler ve lambdalar
Cevap
Foo(const Foo&)
'dur. Lambdalar varsayılan olarak değişmezdir, lambdaya[]
ile yakalanan tüm değerler örtük olarakconst
. Bu, lambdalar için idempotent davranışı açar.
f
hareket ettirdiğinizdeconst Foo&&
oluşturursunuz.const Foo&&
garip bir türdür, bu nedenle derleyici sadeceFoo
kopyalar
Bunu düzeltmenin iki yolu vardır:
Değişken lambda oluştur
auto a = [f = std::move(f)]() mutable { return std::move(f); };
Foo(const Foo&&)
yapıcısını bildirin
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 zamantrue
olur.
bar()
fonksiyonu hiç kullanılmadı, bu sayede bağlantı sırasında referans alınmayan sembol hatalarından kaçınabiliyoruz.
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.