Języki programowania - C i C++ - co wpływa na ich popularność?

Opublikowane: 2022-12-29
Autor: Tomasz Przedziński

Gdy powstawał ten artykuł, nie wiedzieliśmy jeszcze, że w styczniu 2023 TIOBE wybierze C++ językiem roku 2022! Mieliśmy nosa! :wink:

W pierwszej części tej serii artykułów o najpopularniejszych językach programowania skupiliśmy się na języku C#, który w indeksie TIOBE z lipca 2022 zajmował piąte miejsce. Minęły 4 miesiące, a pięć pierwszych pozycji indeksu pozostało bez zmian – każdy z języków utrzymał swoje zaszczytne miejsce na podium, co nie jest rzeczą bardzo zaskakującą1.

 

Tworzymy oprogramowanie na zamówienie: aplikacje mobilne, webowe i systemy wbudowane. Sprawdź dlaczego warto z nami pracować!

 

C i C++ – dwa światy

Dzisiaj skupimy się  na dwóch kolejnych pozycjach od dołu wyróżnionej przez TIOBE piątki, z wyłączeniem języka Java2. Języki C i C++ są w czołówce indeksu od 2001 roku, a omawiamy je w jednym artykule, by pokazać istotne różnice pomiędzy nimi.

Niestety, często kandydaci, z którymi spotykamy się podczas rozmów kwalifikacyjnych, łączą w swoich CV te dwa języki w jedną pozycję – C/C++. Dla mnie, jako osoby, która sprawdza techniczną wiedzę podczas spotkań, jest to sygnał, że kandydat może do końca nie znać różnic między tymi językami – zwykle podejrzewam, że chodzi jedynie o język C++ i zawsze to weryfikuję. Programista C nie zgrupowałby tego języka z jego następcą3. Istotnie różni je nie tylko sposób pracy, ale i projekty, w których je wykorzystujemy.

Język C: wydajność, swoboda, odpowiedzialność

Język C jest najbardziej wyróżniającym się językiem ze wspomnianej piątki. Jako jedyny jest językiem niskopoziomowym, co znacząco wpływa na obszary, w których ma sensowne zastosowanie. Jest językiem zorientowanym na programowanie proceduralne, co nie oznacza oczywiście, że nie można w nim programować funkcyjnie, czy z użyciem praktyk OOP (ang. Object-Oriented Programming). Można, ale sam język programowania C nie zawiera konstrukcji gramatycznych, które by w tym pomagały.

Kod C++

Program “Hello world!” w C

W języku C pisze się wszędzie tam, gdzie liczy się wydajność. Nie posiada on mechanizmów takich jak polimorfizm, zarządzanie pamięcią, zabezpieczenie dostępu do pamięci, czy kontrola typów 4. Brak tych mechanizmów znacząco przyspiesza działanie programu, ale nakłada przy tym sporą odpowiedzialność na programistę – to on musi kontrolować absolutnie wszystko.

Drugim istotnym czynnikiem przemawiającym za użyciem tego języka jest bezpośredni dostęp do zasobów. Brak mechanizmów, które ograniczają swobodę programisty sprawia, że w języku C można łatwo i efektywnie manipulować flagami w rejestrach procesora, dokonywać bezpośrednich wpisów do różnych obszarów pamięci lub manipulować komunikacją z podzespołami urządzenia, na którym pracujemy.

Ta swoboda i wydajność to powody, dla których w języku programowania C powstają sterowniki, jądra systemów operacyjnych, jądra przeglądarek internetowych, fundamenty baz danych, interfejsów graficznych czy silników gier, a także znaczna większość oprogramowania wbudowanego. Gdy myślimy o najniższej warstwie oprogramowania, często jest ona napisana właśnie w języku C.

Gramatyka języka C jest bardzo prosta. Całkiem łatwo napisać w C kod, który realizuje skomplikowaną mechanikę, a skompiluje się bez błędów – nawet jeśli takie się pojawią z reguły są do naprawienia w kilka chwil. Niestety pozorna prostota oznacza też, że niewiele rzeczy jest z góry zagwarantowanych lub sprawdzanych na etapie kompilacji –  bardzo łatwo popełnić w tym języku trudne do wykrycia błędy, które są zwykle nie do pomyślenia we współczesnych językach programowania. Przechodząc z pracy w języku wysokopoziomowym do C, trzeba odrzucić wiele nawyków, a wytworzyć sporo zupełnie nowych.
Kod języka C

Przykład typowego problemu podczas programowania w C. Wskaźniki można dowolnie rzutować (zamieniać na inny typ) i nie da się bezpiecznie tworzyć generycznych funkcji. Zapewnienie poprawności tych rozwiązań leży w całości po stronie programisty.

Kod języka C++

Użycie wskaźników do funkcji jest szczególnie niebezpieczne w języku C. Podanie złego wskaźnika, co w złożonych projektach często zdarza się przypadkiem, może spowodować nieoczekiwane rezultaty. Kompilator ostrzega, ale nie rzuca błędu w takiej sytuacji. Wielokrotnie zresztą z automatu programiści uciszają tego typu ostrzeżenia, myśląc, że dotyczą czego innego.

Chociaż składni języka C można nauczyć się bardzo szybko, jest to jeden z najtrudniejszych języków do operowania w praktyce. Swoboda implementacji rozwiązań oznacza, że ciężko o standaryzację jednego, konkretnego podejścia do rozwiązywania problemów. W projektach pisanych w C programiści wielokrotnie wynajdują koło na nowo5, sprzecznie z praktyką ponownego użycia kodu (ang. code reuse). Takie koło zawsze wygląda nieco inaczej niż poprzednie i wymaga osobnych testów, a bywa że ten proces zachodzi nawet w obrębie jednego produktu, jeśli pracuje nad nim kilka zespołów6.

Dodatkowo, mając narzędzie-wytrych w postaci makr, które pozwalają generować w locie nawet całe bloki kodu, bardzo łatwo stworzyć skomplikowany i trudny w zrozumieniu kod. Nic dziwnego zatem, że jeden zespół może nie chcieć użyć kodu drugiego, współpracującego z nim zespołu.

Warto zauważyć, że duża część kodu napisanego w C, ze względu na optymalizację i dostosowanie go do wyznaczonej platformy, jest przeznaczona tylko pod jedno konkretne zastosowanie. Jednak dobry podział na warstwy i komponenty mógłby sprawić, że część tego kodu dałoby się wykorzystać ponownie. Sam wielokrotnie stosowałem to podejście w projektach, w których brałem udział. Niestety, z mojego doświadczenia, takie podejście jest rzadkością.

Gdy pracuje się na najniższej warstwie oprogramowania, każdy błąd może okazać się krytycznym, a gdy w grę wchodzą kwestie bezpieczeństwa, jedna dziura może spowodować globalne konsekwencje7.

Z kolei w oprogramowaniu wbudowanym, którego aktualizacje rozsyłane są po setkach tysięcy lub milionach egzemplarzy sprzętu, jeden krytyczny błąd może nawet sprawić, że urządzenia zupełnie przestaną działać8. Ktoś, kto choć raz zaimplementował system OTAU (ang. Over-The-Air Update) wie, z jak wielu czynników się składa, jak delikatny jest to proces i jak łatwo popełnić błąd. Stworzenie systemu OTAU wymaga implementacji szeregu zabezpieczeń i złożonej obsługi scenariuszy krytycznych, co powoduje, że bardzo łatwo się pomylić lub zapomnieć o jakimś scenariuszu. Konsekwencją takiej pomyłki może być nawet permanentne uszkodzenie sprzętu kończące się serwisem albo wymianą.

Swoistym paradoksem jest fakt, że do tak krytycznych zadań wykorzystuje się tak niebezpieczny język jakim jest C. Nie dziwi mnie za to rosnąca wśród programistów popularność języka Rust9, którego konstrukcja zdaje się odwrotnością gramatyki języka C – znacząco ogranicza on swobodę programisty, zabezpieczając kod przed wieloma bardzo istotnymi problemami, dając w zamian prawie identyczną wydajność i możliwość niskopoziomowej manipulacji podzespołami i pamięcią, co język programowania C.

Zdecydowanie język C to najtrudniejszy język z jakim przyszło mi pracować, ale nie ze względu na złożoność samego języka, a problemów, które trzeba przy jego pomocy rozwiązywać oraz konieczność ręcznego zabezpieczania dużej ilości kodu przed wieloma błędami. C jest bardzo podstawowym narzędziem, co oznacza, że szczególnie trudno rozwiązywać z jego pomocą złożone problemy. Największa trudność w jego opanowaniu polega na nauczeniu się tworzenia bezpiecznych rozwiązań i unikaniu błędów, co wymaga ogromnej dyscypliny w projekcie i bardzo uważnej analizy kodu, zarówno swojego, jak i innych członków zespołu.

Język C++

Język C++ charakteryzuje zupełnie odmienny zestaw cech niż jego poprzednika. C++ jest obiektowym językiem wysokiego poziomu, choć pozwala na niskopoziomowy dostęp do zasobów tak jak język C. Historyczny bagaż języka C++, w postaci konstruktów z języka C, jest jednym z jego silnych punktów, jak również źródłem największych problemów10. To nie oznacza jednak, że pisze się, czy powinno się pisać, w C++ tak samo jak w C. Wręcz przeciwnie.
Kod C++

Program “Hello world!” w C++.

Biblioteki takie jak standardowa C++ oraz STL (ang. Standard Template Library) dostarczają masę gotowych rozwiązań, które w C trzeba było tworzyć od zera. Nie bez powodu na rozmowach kwalifikacyjnych często padają pytania związane z STL – jej dobra znajomość pozwala szybko i efektywnie rozwiązać wiele podstawowych problemów. Adresuje ona, między innymi, problemy związane z zarządzaniem pamięcią.

Od czasu wejścia na rynek standardu C++11 coraz bardziej odchodzi się już od stosowania „czystych wskaźników” (ang. raw pointer) znanych z C, na rzecz szeregu dostępnych mechanizmów zarządzania pamięcią, takich jak inteligentne wskaźniki (ang. smart pointer). W kwestii refleksji C++ wciąż kuleje za swoimi nowszymi rywalami, ale najbardziej użyteczne mechanizmy, takie jak RTTI (ang. Run Time Type Information)11 i cechy typów, są w nim dostępne. Ma również obsługę wyjątków12.

Język C++, podobnie jak C, używany jest wszędzie tam, gdzie liczy się wydajność, ponieważ większość z mechanizmów spowalniających jego pracę jest opcjonalna13. Można zatem korzystać z wielu udogodnień, które oferuje – bez, lub z niewielkim dodatkowym narzutem. To sprawia, że jego zastosowania w dużej mierze pokrywają się z zastosowaniami języka C. W wielu nowszych projektach (również w systemach wbudowanych) dotykających najniższej warstwy sprzętu korzysta się zarówno z C jak i C++. Jest to popularny język programowania, zwłaszcza w urządzeniach z wbudowanym Linuxem.

Możliwości tego języka pozwalają skutecznie wykorzystać go w prawie każdej dziedzinie. Dzięki użyciu platform takich jak Qt z powodzeniem można w nim rozwijać aplikacje desktopowe. Współczesny C++ posiada szereg mechanizmów programowania asynchronicznego, wliczając mechanizmy tworzenia zadań wykorzystywane w EAP (ang. Event-based Asynchronous Pattern) czy mechanizmy realizujące koncepty „future” i „promise”, wykorzystane w TAP (ang. Task-based Asynchronous Pattern). Jest też powszechnie stosowany jako backend wielu serwisów internetowych. C++ to naprawdę uniwersalny język, który sprawdzi się w każdej roli, jednak  nie do każdej oczywiście jest najlepszym możliwym wyborem.

Istotną bolączką pracy w projektach napisanych w języku C++ jest zarządzanie procesem kompilacji oraz dodatkowymi pakietami. Są to problemy praktycznie nieistniejące w Pythonie i marginalnie znaczące w C#. Do zarządzania kompilacją można użyć wielu zewnętrznych narzędzi – zależnie od tego, w którym roku powstał projekt, mogą to być make, autotools lub współcześnie, najczęściej CMake. Z kolei projekty, które powstały w Visual Studio, kompilowane są zwykle przez narzędzia dostarczone wraz z IDE. Zarządzanie zewnętrznymi bibliotekami wymaga użycia managera pakietów, takiego jak Conan14, który dobrze współgra z narzędziem CMake. Nie są to jednak narzędzia działające niezawodnie i dające ten sam efekt w każdym projekcie czy na każdej platformie. Praca z nimi wymaga trochę obycia i doświadczenia, zwłaszcza jeśli chcemy stworzyć własny pakiet do użycia w innych projektach, czy to własnych czy open-source. Pracując z kodem w C++, nie można zapomnieć o procesie kompilacji, a nawet trzeba poświęcić mu całkiem sporo uwagi, zwłaszcza w kluczowych momentach rozwoju projektu, takich jak rozszerzenie projektu o nowe moduły, dodawanie zależności, wdrożenie lub zmiana procesu CI, itp.

Mimo wielu udogodnień, które pomagają programistom w pracy, C++ to nadal trudny język. Jego konstrukcje gramatyczne zdają się często nienaturalne i wymagają znajomości skomplikowanych mechanizmów, które działają w tle, by w pełni wykorzystać jego moc15. Niezrozumiałe błędy kompilacji, zajmujące dziesiątki stron tekstu, to w pracy z szablonami w C++ normalność. Przykład poniżej należy do jednego z najprostszych. W złożonych projektach szukanie właściwego komunikatu błędu zajmuje sporo czasu i nie zawsze IDE jest w stanie z tym pomóc.

Kod C++
Kod C++

Przykład, który skompilowany przez gcc 9.3 generuje 60 linii błędów. Ostatni komunikat (podany poniżej kodu) może zupełnie zdezorientować początkującego programistę, bo nie jest w niczym związany z faktycznym błędem w kodzie. Programiści języka C++ szybko uczą się przewijać logi błędów do początku, bo zwykle pierwszy komunikat zawiera właściwą informację o błędzie (w tym przypadku: literówka w 7. linii kodu).

Jednak  błędy kompilacji to najprostsze z możliwych, bo wychodzą na powierzchnię od razu. Dużo trudniejsze błędy to te, które na przykład wykluczają RVO (ang. Return-Value Optimization), ignorują lub nieprawidłowo wykorzystują semantyki przenoszenia danych (ang. move semantics), czy jeden z wielu zaawansowanych mechanizmów optymalizacji dostępnych w C++. Potrzeba dużo doświadczenia, by rozpoznać, że  dany mechanizm nie działa poprawnie i zorientować się dlaczego nie działa. Co więcej, mnogość ukrytych mechanizmów, które w różnych sytuacjach zachodzą „w tle” bez informowania o tym programisty, znacząco utrudnia efektywne wykorzystanie tego języka początkującym. To język programowania, w którym mam ponad dziesięć lat doświadczenia, a i tak niejednokrotnie frustrują mnie związane z nim problemy. Bezapelacyjnie, C++ ma największy próg wejścia ze wszystkich współcześnie stosowanych na rynku języków programowania i wymaga wieloletniego doświadczenia, by umiejętnie się nim posługiwać.

Sprawy nie ułatwia fakt, że każda nowa edycja16 wprowadza szereg mechanizmów, które wzbogacają język, ale często zmieniają podejście do niektórych konceptów i wymagają przyzwyczajenia. Z tego powodu wiele projektów decyduje się zatrzymać na określonej wersji standardu C++ i nie aktualizować go do nowszej17 – to jest również powód, dla którego istotne jest wyróżnienie z którą wersją języka dany programista miał jedynie styczność, a z którą spędził więcej czasu.

Wieloletnia stabilność języków programowania

Języki C i C++, mimo ogromu swoich wad, nie muszą się bać o to, że w nadchodzących czasach stracą swoją popularność – zbyt dużo kodu w nich powstało i wciąż wymaga utrzymania, ale też cały czas powstają produkty, do wytworzenia których nadają się najlepiej.  Niemniej C i C++ to rzadko wybory początkujących programistów, głównie dlatego, że istnieją interesujące oferty pracy w konkurencyjnych językach, których dużo łatwiej się nauczyć i efektywnie pracować w krótszym czasie. A jednak, popularność tych języków jest niezmienna, a zapotrzebowanie na specjalistów C i C++ nieustające. Dla tych, którzy nie boją się wyzwań związanych z nauką tych języków, pracy nie zabraknie.

Wspólne technologie

Omówiliśmy już języki programowania C#, C++ oraz C. Serię zakończymy językiem Python, który niewiele ma wspólnego z powyższą trójką, a którego popularność w bardzo krótkim czasie pchnęła go na pierwsze miejsce indeksu. W 2018 roku zajmował jedynie 3% rynku, aktualnie jest to około 17% – co czyni go tak popularnym wyborem wśród programistów? Dowiecie się z trzeciej części serii.

Porozmawiajmy o Twoim projekcie! Nasi inżynierowie zaproponują Ci najlepsze rozwiązania techniczne, dzięki którym wydobędziesz potencjał swojego pomysłu. Obejrzyj projekty, które zrealizowaliśmy z klientami, którzy potrzebowali  oprogramowania na zamówienie.

Jeśli masz gotowy plan działania i opis aplikacji, będziemy w stanie przygotować wycenę nawet w 24 godziny od przesłania specyfikacji. Jeśli nie – nic nie szkodzi. Skontaktuj się z nami i umów na bezpłatną konsultację, aby wspólnie opracować dalsze kroki.

 

1 – Pierwsze cztery pozycje, w kolejności Python, C, Java i C++, zajmują razem 55% w indeksie, zostawiając konkurencję daleko w tyle, a ich miejsca w czołówce zdają się niezagrożone. Od lipca ich pozycje wzrosły łącznie prawie o 7%. Z kolei piąty na liście C#, który był głównym tematem pierwszej części tej serii, utrzymał swoją piątą pozycję, mimo straty udziałów w tym okresie. Zresztą, o czym wspominałem w poprzednim tekście, temu językowi programowania nie są obce skoki popularności.
2 – Dawniej, do prostszych silników gier używało się języka C, ale ze względu na złożoność współczesnych silników obecnie nie praktykuje się takich rozwiązań. W języku Python można pisać gry, ale ze względu na niską wydajność tego silnika są to głównie niewymagające sprzętowo produkcje 2D. Dobrym przykładem jest silnik RenPy, który jest popularnym silnikiem do tworzenia gier typu Visual Novel.
3 – Jak wspominaliśmy, język Java jest pominięty w tej serii tylko dlatego, że jej autor nie ma praktycznego doświadczenia w jego używaniu i nie jest kompetentny mówić o jego zaletach i wadach.
4 – Jedną z największych bolączek C jest manipulacja wskaźnikami do tablic czy struktur danych. Przekazywane wskaźniki mogą dotyczyć obszaru pamięci dowolnego rozmiaru i typu. W złożonych projektach, gdzie funkcje przyjmują generyczne wskaźniki, programista sam musi stworzyć mechanizm informujący z jakim obszarem pamięci mamy w danej chwili do czynienia lub ufać, że dane funkcje zawsze operują tylko na wyznaczonych typach danych.
5 – Na przykład prawie każdy projekt dotyczący systemów wbudowanych prędzej czy później będzie potrzebował bufora cyklicznego. Na rynku są setki bibliotek, które oferują taką strukturę danych, ale ja osobiście nie spotkałem się nawet z jednym projektem, który wykorzystałby taką bibliotekę. Zawsze pisana jest ona na nowo. Oczywiście mówimy o bardzo prostym, ale powszechnym przykładzie. Takich przykładów jest znacznie więcej.
6 – Wynika to głównie z tego, że zespoły wolą zmienić istniejącą implementację lub napisać ją na nowo, zamiast wypracować wspólnie wersję, której mogłyby użyć dwa lub więcej projektów. Czasem jest to wynik potrzeby optymalizacji, a czasem próby przedwczesnej i nieuzasadnionej optymalizacji.
7 – Przykładowo, gdy na jaw wyszła potężna dziura w bibliotece OpenSSL, nazwana Heartblead, szacowało się, że około 17% serwerów posiadających certyfikaty nadane przez CA (Certification Authority) było podatnych na atak, który pozwalał m.in. poznać prywatne klucze serwera, podsłuchać całe połączenie z serwerem czy wykonać atak typu man-in-the-middle. Jak grzyby po deszczu zaczęły pojawiać się strony, aplikacje i dodatki do przeglądarek analizujące czy serwery, z którymi się łączymy, są podatne na tą dziurę. W grę wchodziło bezpieczeństwo każdego użytkownika Internetu. Od tamtego czasu wykryto szereg nowych dziur w bibliotece OpenSSL o najwyższej możliwej ocenie zagrożenia, wynoszącej 10. Najnowsza taka dziura pochodzi z 1. lipca tego roku.
8 – Opublikowana w marcu 2022 roku aktualizacja MacOS do wersji 12.3 spowodowała, że ogromna ilość urządzeń ze zmienioną płytą główną przestała się uruchamiać. Obejściem tego problemu była pracochłonna procedura przywracająca działanie urządzeń.
9 – Rust siódmy rok z rzędu został uznany przez użytkowników StackOverflow jako „most loved”, czyli język, w którym największa ilość ankietowanych, bo aż 87%, chce nadal pracować. Niedawno Linus Torvalds, główny autor jądra Linuxa, oświadczył, że najdalej w 2023 roku pierwsze moduły napisane w Rust powinny znaleźć się w jądrze Linux. Z kolei Google rozpoczął przepisywanie fragmentów systemu operacyjnego Android do Rust. W październiku Rust ponownie wskoczył do top-20 języków w indeksie TIOBE. Jego popularność wciąż rośnie, co ukazuje, że programiści pracujący na najniższej warstwie oprogramowania widzą potrzebę i doceniają istnienie języka, który narzuca szereg bardzo sztywnych zasad, ale daje w zamian bezpieczeństwo i znacznie większą kontrolę nad działaniem programu.
10 – W C++ nadal są makra, choć większość zastosowań tych makr można zastąpić szablonami i nowymi składniami wprowadzonymi w C++20. Nadal można w C++ pisać proceduralnie, choć nie wykorzystamy wtedy większości możliwości tego języka. Można w C++ zarządzać pamięcią tak jak w języku C, choć istnieje szereg nowych mechanizmów znacznie ułatwiających tę pracę. Można też zrobić co się chce ze wskaźnikami do obszarów pamięci, choć znów, C++ dodaje masę mechanizmów zabezpieczających przed podstawowymi błędami wynikającymi ze złego użycia wskaźników. Technicznie, kod w C z bardzo niewielkimi wyjątkami da się skompilować kompilatorem kodu C++. Ale, oczywiście, nie odwrotnie.
11 – Co ciekawe, jest głęboka świadomość kosztu w postaci obniżonej wydajności, jaki mechanizm RTTI wprowadza w projekcie, dlatego też RTTI można wyłączyć w wielu kompilatorach C++, uniemożliwiając jego użycie w projekcie.
12 – Podobnie jak z RTTI, narzut związany z rzucaniem wyjątków jest na tyle duży, że często użycie wyjątków w C++ uznawane jest za złą praktykę. Kompilatory zwykle również pozwalają zablokować ich użycie. Moim zdaniem „zła karma” dotycząca wyjątków dotyczy nie tyle kosztu ich użycia, co braku doświadczenia programistów w ich używaniu oraz kosztu nieprawidłowego ich stosowania. Nie bez powodu te mechanizmy są kluczowe we wszystkich innych wysokopoziomowych językach programowania.
13 – Pomijając wspomniane wcześniej mechanizmy RTTI czy obsługi wyjątków, które można wyłączyć, nic nie zmusza programisty C++ do używania dziedziczenia i polimorfizmu. C++ posiada również możliwość dziedziczenia po wielu klasach, co w przypadku, gdy klasy bazowe nie są czysto abstrakcyjne, jest bardzo wolnym mechanizmem. Nikt jednak nie wymaga by z tego mechanizmu korzystać i jest to nawet powszechnie uważane za złą praktykę.
14 – Paradoksalnie instalowany managerem pakietów Pythona.
15 – Dla przykładu, jakkolwiek wielu programistów rozumie na czym polega unikalny dla C++ koncept SFINAE (ang. Substitution Failure Is Not An Error), to na wagę złota jest programista, który jest w stanie poprawnie wymienić wszystkie etapy rozwiązywania przeciążonych nazw (ang. Overload resolution), nie mówiąc już o poprawnym zastosowaniu tej wiedzy w praktyce.
16 – Obecnie wiodąca wersja to C++20. Prace nad C++23, który zgodnie z notacją miałby być opublikowany w 2023 roku, wciąż trwają.
17 – W środowiskach systemów wbudowanych najpopularniejszy jest standard C++11, choć powoli wchodzi w nie C++14. W branży automotive powszechnie stosowany jest C++14. Jest to również obecnie najszerzej używana wersja w projektach na rynku. C++17 powoli wkracza w istniejące projekty. Im nowsze, tym więcej ich elementów jest napisanych w C++17. Natomiast C++20 osobiście spotykam jedynie w ofertach pracy na nowe stanowiska. Nie zauważam jeszcze jego powszechniejszego użycia w istniejących projektach.
Autor: Tomasz Przedziński,
Architekt Oprogramowania

Rocznik 86, skończył studia magisterskie z Informatyki Stosowanej na Uniwersytecie Jagiellońskim w Krakowie i obronił doktorat z inżynierii oprogramowania na AGH. Specjalizuje się w C++, ale mocno polubił się ze środowiskami embedded. Nie ukrywa sympatii do algorytmiki i optymalizacji rozwiązań. W pracy zawodowej stawia na jakość, budując zaawansowane środowiska testowe lub rozbudowując istniejące.

SKONTAKTUJ SIĘ
Wypełnij
formularz.
Skontaktujemy się z Tobą,
żeby umówić rozmowę
w dogodnym dla Ciebie terminie.