Programiranje

Zakaj še vedno vlada programski jezik C.

Nobena tehnologija se ne zadržuje 50 let, razen če svoje delo opravlja bolje kot karkoli drugega - še posebej računalniška tehnologija. Programski jezik C živi in ​​brca že od leta 1972 in še vedno kraljuje kot eden temeljnih gradnikov našega programsko opredeljenega sveta.

Toda včasih se tehnologija drži, ker je ljudje preprosto niso prišli zamenjati. V zadnjih nekaj desetletjih se je pojavilo na desetine drugih jezikov - nekateri so bili izrecno namenjeni izzivu prevlade C-ja, nekateri pa so stran C-ja odstranili kot stranski produkt njihove priljubljenosti.

Ni težko trditi, da je treba C zamenjati. Raziskave programskega jezika in prakse razvoja programske opreme namigujejo, kako obstajajo boljši načini za ravnanje kot C-jev način. Toda C še vedno vztraja, za tem pa desetletja raziskav in razvoja. Le redki drugi jeziki ga lahko premagajo zaradi zmogljivosti, združljivosti golih kovin ali vseprisotnosti. Kljub temu je vredno videti, kako se C uvršča proti jezikovnemu tekmovanju z velikimi imeni v letu 2018.

C v primerjavi s C ++

Seveda se C najpogosteje primerja s C ++, jezikom, ki je - kot že samo ime pove - ustvarjen kot podaljšek C. Razlike med C ++ in C bi lahko označili kot obsežne oz.pretirano, odvisno od tega, koga vprašate.

Čeprav je C ++ po svoji sintaksi in pristopu podoben C, ponuja številne resnično uporabne funkcije, ki v jeziku C niso na voljo: imenski prostori, predloge, izjeme, samodejno upravljanje pomnilnika itd. Projekti, ki zahtevajo vrhunsko zmogljivost - zbirke podatkov, sistemi strojnega učenja - so pogosto napisani v jeziku C ++ z uporabo teh funkcij, da se iz sistema iztisne vsak padec zmogljivosti.

Poleg tega se C ++ še naprej širi veliko bolj agresivno kot C. Prihajajoči C ++ 20 prinaša v tabelo še več, vključno z moduli, podprogrami, sinhronizacijsko knjižnico in koncepti, ki olajšajo uporabo predlog. Najnovejša revizija standarda C doda le malo in se osredotoča na ohranjanje združljivosti z nazaj.

Stvar je v tem, da lahko vsi plusi v C ++ delujejo tudi kot minusi. Velike. Več kot uporabljate funkcij C ++, več zapletenosti uvajate in težje je ukrotiti rezultate. Razvijalci, ki se omejijo na podskupino C ++, se lahko izognejo številnim najhujšim pastem in ekscesom. Toda nekatere trgovine se želijo zaščititi pred zapletenostjo C ++. Če se držite C, se razvijalci omejijo na to podskupino. Na primer, skupina za razvoj jedra Linuxa se izogiba C ++.

Izbiranje C nad C ++ je način, s katerim se boste - in vsi razvijalci, ki ohranjajo kodo po vas - izognili pretiravanju s C ++, tako da sprejmete prisilni minimalizem. Seveda ima C ++ z dobrim razlogom bogat nabor funkcij na visoki ravni. Toda če je minimalizem bolj primeren za sedanje in prihodnje projekte - in projekte ekipe- potem je C bolj smiseln.

C proti Javi

Po desetletjih ostaja Java osnovna rešitev za razvoj programske opreme v podjetju - in na splošno glavni razvoj. Številni najpomembnejši projekti programske opreme za podjetja so bili napisani v Javi - vključno z veliko večino projektov Apache Software Foundation - in Java ostaja dober jezik za razvoj novih projektov, ki ustrezajo zahtevam podjetja.

Sintaksa Java si veliko izposoja od C in C ++. V nasprotju s C pa Java privzeto ne prevaja v izvorno kodo. Namesto tega izvajalno okolje Java, JVM, JIT (ravno pravočasno), prevede kodo Java za zagon v ciljnem okolju. Koda Java v ustreznih okoliščinah se lahko približa ali celo preseže zmogljivost C.

Filozofija »enkrat napiši, zaženi kjer koli«, ki stoji za Java, omogoča tudi izvajanje programov Java s sorazmerno malo prilagoditev za ciljno arhitekturo. V nasprotju s tem, čeprav je bil C prenesen na veliko arhitektur, bo morda kateri koli program C še vedno potreboval prilagoditev, da bo pravilno deloval, recimo, v primerjavi z Windowsom in Linuxom.

Ta kombinacija prenosljivosti in močne zmogljivosti, skupaj z ogromnim ekosistemom knjižnic in okvirov programske opreme, naredijo Javo uporabni jezik in izvajalno okolje.

Tam, kjer Java ne dosega C, je področje, na katerem Java nikoli ni bila namenjena tekmovanju: tek blizu kovine ali neposredno delo s strojno opremo. Koda C se prevede v strojno kodo, ki jo postopek izvrši neposredno. Java je prevedena v bajtno kodo, ki je vmesna koda, ki jo interpreter JVM nato pretvori v strojno kodo. Poleg tega, čeprav je samodejno upravljanje pomnilnika Java v večini primerov blagoslov, je C bolj primeren za programe, ki morajo optimalno izkoristiti omejene pomnilniške vire.

Kljub temu obstajajo nekatera področja, kjer se Java lahko hitrosti približa C. JVM-jev mehanizem JIT optimizira rutine med izvajanjem na podlagi vedenja programov in omogoča številne razrede optimizacije, ki niso možni s predčasno sestavljenim C. In medtem ko Java izvajalno okolje avtomatizira upravljanje pomnilnika, nekatere novejše aplikacije delujejo okoli tega. Na primer, Apache Spark delno optimizira obdelavo v pomnilniku z uporabo kode za upravljanje pomnilnika po meri, ki zaobide JVM.

C proti C # in .Net

Skoraj dve desetletji po njihovi uvedbi C # in .Net Framework ostajata pomemben del poslovnega sveta podjetja. Rečeno je bilo, da sta bili C # in .Net Microsoftov odgovor na Javo - sistem prevajalskega prevajalskega koda in univerzalni čas izvajanja - in toliko primerjav med C in Javo drži tudi za C in C # /. Net.

Tako kot Java (in do neke mere Python) .Net ponuja prenosljivost na različnih platformah in širok ekosistem integrirane programske opreme. To niso majhne prednosti glede na to, koliko v podjetju .Net poteka razvoj, usmerjen v podjetja. Ko razvijete program v jeziku C # ali katerem koli drugem jeziku .Net, lahko črpate iz vesolja orodij in knjižnic, napisanih za izvajanje .Net.

Še ena podobnost Java-u .NET je optimizacija JIT. Programa C # in .Net je mogoče vnaprej sestaviti v skladu s C, vendar so večinoma pravočasno sestavljeni v času izvajanja .Net in optimizirani z informacijami o času izvajanja. Kompilacija JIT omogoča vse vrste optimizacij na mestu za tekoči program .Net, ki ga ni mogoče izvesti v C.

Tako kot C, C # in .Net ponujajo različne mehanizme za neposreden dostop do pomnilnika. Kup, sklad in neupravljani sistemski pomnilnik so dostopni prek .Net API-jev in predmetov. In razvijalci lahko uporabljajo nevarno v .Net za doseganje še večje učinkovitosti.

Nič od tega pa ni na voljo brezplačno. Upravljani predmeti in nevarno predmetov ni mogoče samovoljno zamenjati, marširanje med njimi pa ima stroške izvedbe. Zato maksimiranje zmogljivosti .Net aplikacij pomeni čim manjše gibanje med upravljanimi in neupravljanimi predmeti.

Kadar si ne morete privoščiti plačila kazni za upravljani in neupravljani pomnilnik ali kadar je izvajalno okolje .Net slaba izbira za ciljno okolje (npr. Prostor jedra) ali morda sploh ni na voljo, potem je C tisto, kar potrebujejo. In za razliko od C # in .Net, C privzeto odklene neposreden dostop do pomnilnika.

C proti Go

Sintaksa Go je zelo dolžna C - zavite oklepaje kot ločila, stavke, zaključene s podpičji itd. Razvijalci, ki obvladajo C, lahko brez večjih težav navadno skočijo naravnost v Go, tudi ob upoštevanju novih funkcij Go, kot so prostori imen in upravljanje paketov.

Bralna koda je bila eden vodilnih ciljev podjetja Go: razvijalcem olajšati hitrost s katerim koli projektom Go in v kratkem času usposobiti bazo kod. Zbirke kod C je težko pretresti, saj se nagibajo k temu, da se spremenijo v podgano gnezdo makrov in #ifdefspecifične tako za projekt kot za določeno skupino. Sintaksa Go in vgrajena orodja za oblikovanje kode in upravljanje projektov naj bi preprečevala tovrstne institucionalne težave.

Go vsebuje tudi dodatke, kot so programi in kanali, orodja na ravni jezika za obdelavo sočasnosti in prenašanje sporočil med komponentami. C bi zahteval, da bi takšne stvari ročno valjali ali dobavljali zunanji knjižnici, vendar jih Go ponuja takoj, kar olajša izdelavo programske opreme, ki jih potrebuje.

Kjer se Go najbolj razlikuje od C pod pokrovom, je upravljanje pomnilnika. Predmeti Go samodejno upravljajo in smeti zbirajo po privzetku. Za večino programov je to izjemno priročno. Pomeni pa tudi, da bo težje napisati vsak program, ki zahteva deterministično ravnanje s pomnilnikom.

Go vključuje nevarno paket za izogibanje nekaterim Go-ovim varnostim pri ravnanju, na primer branje in pisanje poljubnega pomnilnika z a Kazalec tip. Ampak nevarno prihaja z opozorilom, da z njim napisani programi "morda niso prenosljivi in ​​niso zaščiteni s smernicami za združljivost Go 1".

Go je zelo primeren za gradnjo programov, kot so pripomočki ukazne vrstice in omrežne storitve, ker le redko potrebujejo tako natančne manipulacije. Toda nizke ravni gonilnikov naprav, komponente operacijskega sistema v prostoru jedra in druge naloge, ki zahtevajo natančen nadzor nad postavitvijo in upravljanjem pomnilnika, je najbolje ustvariti v C.

C proti Rustu

Rust je na nek način odgovor na uganke za upravljanje pomnilnika, ki so jih ustvarili C in C ++, pa tudi na številne druge pomanjkljivosti teh jezikov. Rust se prevede v izvorno strojno kodo, zato se glede zmogljivosti šteje za enakega C. Varnost spomina je privzeto Rustova glavna prodajna točka.

Rustova pravila skladnje in prevajanja pomagajo razvijalcem, da se izognejo običajnim napakam pri upravljanju pomnilnika. Če ima program težavo z upravljanjem pomnilnika, ki prekriva sintakso Rust, se preprosto ne bo prevedel. Novinci v jeziku, zlasti iz jezika, kot je C, ki ponuja dovolj prostora za takšne napake, prvo fazo svojega izobraževanja o Rustu preživijo v učenju, kako pomiriti prevajalnika. Toda zagovorniki Rusta trdijo, da ima ta kratkoročna bolečina dolgoročno korist: varnejša koda, ki ne žrtvuje hitrosti.

Rja s svojim orodjem izboljša tudi C. Upravljanje projektov in komponent je del verige orodij, ki je privzeto opremljena z Rustom, tako kot Go. Obstaja privzeti, priporočen način upravljanja paketov, organiziranja map projektov in ravnanja s številnimi drugimi stvarmi, ki so v jeziku C v najboljšem primeru priložnostne, pri čemer vsak projekt in ekipa ravnata drugače.

Kljub temu tisto, kar v Rustu označujejo kot prednost, se razvijalcu C morda ne zdi takšno. Rustovih varnostnih funkcij med prevajanjem ni mogoče onemogočiti, zato mora biti tudi najbolj trivialni program Rust skladen z varnostnimi zahtevami Rusta glede pomnilnika. C je morda privzeto manj varen, vendar je veliko bolj prilagodljiv in po potrebi odpušča.

Druga možna pomanjkljivost je velikost jezika Rust. C ima relativno malo funkcij, tudi če upoštevamo standardno knjižnico. Nabor funkcij Rust se širi in še naprej raste. Tako kot pri C ++ tudi večji nabor funkcij Rust pomeni večjo moč, hkrati pa tudi večjo zapletenost. C je manjši jezik, vendar ga je veliko lažje miselno modelirati, zato je morda bolj primeren za projekte, kjer bi Rust pretiraval.

C proti Pythonu

Danes se zdi, da kadar koli govori o razvoju programske opreme, v pogovor vedno vstopi Python. Navsezadnje je Python "drugi najboljši jezik za vse" in nedvomno eden najbolj vsestranskih, saj je na voljo na tisoče neodvisnih knjižnic.

Kar Python poudarja in kjer se najbolj razlikuje od C, daje prednost hitrosti razvoja kot hitrosti izvedbe. Program, ki bi lahko trajal eno uro, da se sestavi v drugem jeziku - na primer C -, bi lahko v Pythonu sestavili v nekaj minutah. Na drugi strani lahko zagon programa v C traja nekaj sekund, v Pythonu pa minuto. (Dobro pravilo: Programi Python običajno tečejo veliko počasneje kot njihovi kolegi C.) Toda za mnoga dela na sodobni strojni opremi je Python dovolj hiter in to je bilo ključno za njegovo uveljavitev.

Druga velika razlika je upravljanje pomnilnika. Programi Python v celoti upravljajo s pomnilnikom s pomočjo izvajalnega okolja Python, zato razvijalcem ni treba skrbeti, ali je dodeljevanje in osvobajanje pomnilnika nepomembno. Toda tudi tu lahkotnost razvijalcev stane na račun izvedbe. Pisanje programov C zahteva skrbno pozornost pri upravljanju pomnilnika, toda nastali programi so pogosto zlati standard za čisto hitrost stroja.

Pod kožo pa imata Python in C globoko povezavo: referenčni izvajalni čas Pythona je napisan v jeziku C. To programom Python omogoča zavijanje knjižnic, napisanih v C in C ++. Pomembni deli ekosistema Python neodvisnih knjižnic, na primer za strojno učenje, imajo v jedru kodo C.

Če je hitrost razvoja pomembnejša od hitrosti izvajanja in če je večino zmogljivih delov programa mogoče izolirati v samostojne komponente (v nasprotju s širjenjem po kodi), bodisi čisti Python bodisi mešanica knjižnic Python in C boljša izbira kot samo C. V nasprotnem primeru C še vedno vlada.