Programování

Proč programovací jazyk C stále vládne

Žádná technologie se neuchytí po dobu 50 let, pokud nedělá svou práci lépe než většina ostatních - zejména počítačová technologie. Programovací jazyk C je živý a nakopává se od roku 1972 a stále vládne jako jeden ze základních stavebních kamenů našeho softwarově definovaného světa.

Někdy však technologie přetrvává, protože lidé se k výměně nedostali. Za posledních několik desetiletí se objevily desítky dalších jazyků - některé byly výslovně navrženy tak, aby zpochybňovaly dominanci C, jiné se oddělovaly od C jako vedlejší produkt jejich popularity.

Není těžké tvrdit, že je třeba C vyměnit. Výzkum programovacího jazyka a postupy vývoje softwaru vše naznačují, že existují mnohem lepší způsoby, jak dělat věci, než způsob C. Ale C přetrvává stejně, s desítkami let výzkumu a vývoje za sebou. Několik dalších jazyků jej může porazit kvůli výkonu, kompatibilitě s holým kovem nebo všudypřítomnosti. Přesto stojí za to vidět, jak se C v roce 2018 postaví proti jazykové konkurenci velkých jmen.

C vs. C ++

C se přirozeně nejčastěji porovnává s C ++, jazykem, který - jak sám název napovídá - byl vytvořen jako rozšíření C. Rozdíly mezi C ++ a C lze charakterizovat jako rozsáhlé, nebonadměrný, podle toho, koho se ptáte.

I když je C ++ stále ve své syntaxi a přístupu, poskytuje mnoho skutečně užitečných funkcí, které v C nativně nejsou k dispozici: jmenné prostory, šablony, výjimky, automatická správa paměti atd. Projekty, které vyžadují špičkový výkon - databáze, systémy strojového učení - jsou často psány v C ++ pomocí těchto funkcí, aby vytlačily ze systému každý pokles výkonu.

C ++ se dále rozšiřuje mnohem agresivněji než C. Nadcházející C ++ 20 přináší do tabulky ještě více, včetně modulů, korutin, synchronizační knihovny a konceptů, které usnadňují používání šablon. Nejnovější revize standardu C přidává jen málo a zaměřuje se na zachování zpětné kompatibility.

Věc je, že všechny plusy v C ++ mohou fungovat také jako minusy. Ty velké. Čím více funkcí C ++ použijete, tím složitější představíte a tím obtížnější bude výsledky zkrotit. Vývojáři, kteří se omezují na podmnožinu C ++, se mohou vyhnout mnoha nejhorším nástrahám a excesům. Některé obchody se ale chtějí chránit před složitostí C ++. Držení se C nutí vývojáře omezit se na tuto podmnožinu. Například vývojový tým pro linuxové jádro se vyhýbá C ++.

Výběr C nad C ++ je pro vás - a všechny vývojáře, kteří po vás udržují kód - způsob, jak se vyhnout nutnosti zamotávat se s excesy v C ++ přijetím vynuceného minimalismu. C ++ má samozřejmě z dobrého důvodu bohatou sadu funkcí na vysoké úrovni. Ale pokud je minimalismus vhodnější pro současné i budoucí projekty - a projekt týmy—Pak C dává větší smysl.

C vs. Java

Po desetiletích zůstává Java jádrem vývoje podnikového softwaru - a základem vývoje obecně. Mnoho z nejvýznamnějších projektů podnikového softwaru bylo napsáno v jazyce Java - včetně velké většiny projektů Apache Software Foundation - a Java zůstává životaschopným jazykem pro vývoj nových projektů s požadavky na podnikové úrovni.

Syntaxe Java si z C a C ++ hodně půjčuje. Na rozdíl od C se však Java ve výchozím nastavení nezkompiluje do nativního kódu. Místo toho běhové prostředí Java, JVM, JIT (just-in-time) kompiluje kód Java tak, aby běžel v cílovém prostředí. Za správných okolností může JITted Java kód přiblížit nebo dokonce překonat výkon C.

Filozofie „write once, run anywhere“, která stojí za Javou, také umožňuje, aby programy Java běžely s relativně malým vyladěním pro cílovou architekturu. Naproti tomu, i když byl C portován na mnoho architektur, může jakýkoli daný program C stále potřebovat přizpůsobení, aby správně fungoval, řekněme, Windows versus Linux.

Tato kombinace přenositelnosti a vysokého výkonu spolu s obrovským ekosystémem softwarových knihoven a frameworků činí z Javy jazyk go-to a runtime pro vytváření podnikových aplikací.

Tam, kde Java nedosahuje C, je oblast, kde Java nikdy neměla konkurovat: běh blízko kovu nebo práce přímo s hardwarem. C kód je kompilován do strojového kódu, který je prováděn přímo procesem. Java je kompilován do bytecode, což je přechodný kód, který interpret JVM poté převede na strojový kód. Ačkoliv je automatická správa paměti Java ve většině případů požehnáním, C je vhodnější pro programy, které musí optimálně využívat omezené paměťové zdroje.

To znamená, že v některých oblastech se Java může z hlediska rychlosti přiblížit C. Engine JVM JIT optimalizuje rutiny za běhu na základě chování programu, což umožňuje mnoho tříd optimalizace, které nejsou možné s předem zkompilovaným C. A zatímco runtime Java automatizuje správu paměti, některé novější aplikace to obcházejí. Například Apache Spark optimalizuje zpracování v paměti částečně pomocí vlastního kódu správy paměti, který obchází JVM.

C vs. C # a .Net

Téměř dvě desetiletí po jejich zavedení zůstávají C # a .Net Framework hlavní součástí světa podnikového softwaru. Bylo řečeno, že C # a .Net byly odpovědí Microsoftu na Javu - systém kompilátoru spravovaného kódu a univerzální běhový modul - a tolik srovnání mezi C a Javou také platí pro C a C # /. Net.

Stejně jako Java (a do určité míry i Python) nabízí .Net přenositelnost napříč různými platformami a rozsáhlým ekosystémem integrovaného softwaru. To nejsou malé výhody vzhledem k tomu, kolik podnikově orientovaného vývoje probíhá ve světě .Net. Když vyvíjíte program v C # nebo jiném jazyce .Net, můžete čerpat z vesmíru nástrojů a knihoven vytvořených pro běh .Net.

Další výhodou .NET, podobnou prostředí Java, je optimalizace JIT. Programy C # a .Net lze kompilovat předem podle C, ale jsou to hlavně just-in-time kompilované runtime .Net a optimalizované runtime informacemi. Kompilace JIT umožňuje nejrůznější místní optimalizace pro spuštěný program .Net, který nelze provést v C.

Stejně jako C, C # a .Net poskytují různé mechanismy pro přímý přístup k paměti. Halda, zásobník a nespravovaná systémová paměť jsou všechny přístupné prostřednictvím .Net API a objektů. A vývojáři mohou používat nebezpečný v režimu .Net k dosažení ještě vyššího výkonu.

Nic z toho však není zadarmo. Spravované objekty a nebezpečný objekty nelze libovolně vyměňovat a zařazování mezi nimi má cenu výkonu. Proto maximalizace výkonu aplikací .Net znamená udržovat pohyb mezi spravovanými a nespravovanými objekty na minimum.

Pokud si nemůžete dovolit zaplatit pokutu za spravovanou vs. nespravovanou paměť, nebo když je běh .Net špatnou volbou pro cílové prostředí (např. Prostor jádra) nebo nemusí být k dispozici vůbec, pak C je to, co potřeba. A na rozdíl od C # a .Net C ve výchozím nastavení odemkne přímý přístup do paměti.

C vs. Go

Přejít na syntaxi dluží C hodně - složené závorky jako oddělovače, příkazy zakončené středníky atd. Vývojáři ovládající jazyk C mohou obvykle bez větších potíží skočit přímo do Go, a to i při zohlednění nových funkcí Go, jako jsou jmenné prostory a správa balíčků.

Jedním z hlavních cílů designu společnosti Go byl čitelný kód: Usnadněte vývojářům dostat se do rychlosti s jakýmkoli projektem Go a v krátké době zvládnout kódovou základnu. C codebases může být těžké pochopit, protože jsou náchylné proměnit se v krysí hnízdo maker a #ifdefjsou specifické jak pro projekt, tak pro daný tým. Goova syntaxe a její vestavěné nástroje pro formátování kódu a správu projektů jsou určeny k udržení těchto institucionálních problémů na uzdě.

Go také obsahuje doplňky, jako jsou goroutiny a kanály, nástroje na úrovni jazyka pro zpracování souběžnosti a předávání zpráv mezi komponentami. C by vyžadovalo, aby takové věci byly ručně srolovány nebo dodávány externí knihovnou, ale Go je poskytuje hned po vybalení, takže je mnohem snazší vytvářet software, který je potřebuje.

To, kde se Go nejvíce liší od C pod kapotou, je správa paměti. Go objekty jsou ve výchozím nastavení automaticky spravovány a shromažďovány odpadky. Pro většinu programovacích úloh je to mimořádně výhodné. Ale také to znamená, že jakýkoli program, který vyžaduje deterministické zacházení s pamětí, bude těžší napsat.

Go obsahuje nebezpečný balíček pro obcházení některých bezpečnostních opatření pro manipulaci s typem Go, jako je čtení a zápis libovolné paměti pomocí a Ukazatel typ. Ale nebezpečný přichází s varováním, že programy s ním napsané „nemusí být přenosné a nejsou chráněny pokyny pro kompatibilitu Go 1“.

Go je vhodný pro vytváření programů, jako jsou nástroje příkazového řádku a síťové služby, protože takové jemnohmotné manipulace zřídka potřebují. Ovladače zařízení na nízké úrovni, součásti operačního systému v prostoru jádra a další úlohy, které vyžadují náročnou kontrolu nad rozložením a správou paměti, se nejlépe vytvářejí v C.

C vs. Rust

V některých ohledech je Rust odpovědí na hlavolamy správy paměti vytvořené v C a C ++ a také na mnoho dalších nedostatků těchto jazyků. Rust se kompiluje s nativním strojovým kódem, takže je považován za srovnatelný s C, pokud jde o výkon. Bezpečnost paměti je ve výchozím nastavení hlavním Rustovým prodejním místem.

Rustova pravidla syntaxe a kompilace pomáhají vývojářům vyhnout se běžným chybám při správě paměti. Pokud má program problém se správou paměti, který překračuje Rustovu syntaxi, jednoduše se nezkompiluje. Nováčci v jazyce, zejména z jazyka, jako je C, který poskytuje dostatek prostoru pro takové chyby, tráví první fázi svého vzdělávání Rust učením, jak uklidnit kompilátor. Zastánci Rustu však tvrdí, že tato krátkodobá bolest má dlouhodobou výplatu: bezpečnější kód, který neobětuje rychlost.

Rust také vylepšuje C pomocí svých nástrojů. Správa projektů a komponent je ve výchozím nastavení součástí sady nástrojů dodávané s Rustem, stejně jako u Go. Existuje výchozí doporučený způsob, jak spravovat balíčky, organizovat složky projektu a zpracovávat mnoho dalších věcí, které jsou v jazyce C v nejlepším případě ad-hoc, přičemž každý projekt a tým je zpracovávají jinak.

To, co se v Rustu říká jako výhoda, se vývojářům C nemusí zdát jako jedna. Bezpečnostní funkce Rustu v době kompilace nelze deaktivovat, takže i ten nejtriviálnější program Rust musí odpovídat bezpečnostním omezením Rustovy paměti. C může být ve výchozím nastavení méně bezpečné, ale v případě potřeby je mnohem pružnější a odpouštějící.

Další možnou nevýhodou je velikost jazyka Rust. C má relativně málo funkcí, i když vezmeme v úvahu standardní knihovnu. Sada funkcí Rust se rozléhá a stále roste. Stejně jako v C ++ znamená větší sada funkcí Rust více síly, ale také složitější. C je menší jazyk, ale je mnohem snazší jej mentálně modelovat, takže se možná lépe hodí pro projekty, kde by byl Rust přehnaný.

C vs. Python

V dnešní době, kdykoli se jedná o vývoj softwaru, se zdá, že do konverzace vždy vstupuje Python. Nakonec je Python „druhým nejlepším jazykem pro všechno“ a je nepochybně jedním z nejvšestrannějších, s tisíci knihoven třetích stran.

To, co Python zdůrazňuje, a kde se nejvíce liší od C, je upřednostňování rychlosti vývoje před rychlostí provedení. Program, jehož sestavení v jiném jazyce - například C - může trvat hodinu, může být v Pythonu sestaven během několika minut. Na druhou stranu tento program může trvat několik sekund, než se spustí v C, ale minuta, než se spustí v Pythonu. (Dobré pravidlo: Programy Pythonu obecně běží o řád pomaleji než jejich protějšky C.) Ale pro mnoho úloh na moderním hardwaru je Python dostatečně rychlý a to bylo klíčem k jeho využití.

Dalším významným rozdílem je správa paměti. Programy v Pythonu jsou plně spravovány pamětí za běhu Pythonu, takže si vývojáři nemusí dělat starosti s hloupostí přidělování a uvolňování paměti. Ale i zde zase vývojářská lehkost přichází za cenu běhového výkonu. Psaní programů C vyžaduje pečlivou pozornost správy paměti, ale výsledné programy jsou často zlatým standardem pro čistou rychlost stroje.

Pod skinem však Python a C sdílejí hluboké spojení: referenční runtime Pythonu je napsán v C. To umožňuje programům Pythonu zabalit knihovny napsané v C a C ++. Významné části pythonového ekosystému knihoven třetích stran, například pro strojové učení, mají v jádru kód C.

Pokud na rychlosti vývoje záleží víc než na rychlosti provedení a pokud lze většinu výkonných částí programu izolovat do samostatných komponent (na rozdíl od rozšíření v celém kódu), buď čistý Python, nebo kombinace knihoven Python a C lepší volba než samotný C. Jinak C stále vládne.