A C egy általános célú programozási nyelv, melyet Dennis Ritchie fejlesztett ki Ken Thompson segítségével 1969 és 1973 között a UNIX rendszerekre az AT&T Bell Labs-nál. Idővel jóformán minden operációs rendszerre készítettek C fordítóprogramot, és a legnépszerűbb programozási nyelvek egyikévé vált. Rendszerprogramozáshoz és felhasználói programok készítéséhez egyaránt jól használható. Az oktatásban és a számítógép-tudományban is jelentős szerepe van.
A C minden idők legszélesebb körben használt programozási nyelve, és a C fordítók elérhetők a ma elérhető számítógép-architektúrák és operációs rendszerek többségére. Elterjedésében fontos szerepet játszott a RISC technológia. A sokféle processzorhoz operációs rendszerekre volt szükség, és az eleve C-ben írt Unix volt a legkönnyebben portolható.
Történet Korai fejlesztések
A kezdeti fejlesztések az AT&T berkein belül történtek 1969 és 1973 között. A legkreatívabb időszak, Ritchie-nek köszönhetően 1972-ben volt. Azért lett „C” a nyelv neve, mert egy korábbi, „B” nevű programozási nyelv sok tulajdonságát „örökölte”. A leírások különböznek a „B” név forrását illetően: Ken Thompson írt egy programozási nyelvet, a BCPL-t, de írt egy Bon nevűt is, a feleségéről (Bonnie-ról) elnevezve.
Az 1973-as évben a C nyelv elég hatékonnyá vált, így a UNIX rendszermag legnagyobb részét, melyek PDP-11/20 assembly nyelven íródtak, újraírták C-ben. Ez volt az egyik első operációs rendszer rendszermag, mely nem assembly nyelven íródott, korábbiak, a Multics PL/I-ben íródott, a TRIPOS BCPL-ben.
K&R C
1978-ban megjelent a Dennis Ritchie és Brian Kernighan nevével fémjelzett A C programozási nyelv c. könyv első kiadása. Ez a könyv, melyet a C programozók csak K&R néven emlegettek, sokáig szolgált a nyelv formai leírásának forrásaként. A C nyelvnek az a verziója, melyet leírt, az a „K&R C” nyelv. (A könyv második kiadása az „ANSI C” szabványt írta le, lásd alább.)
A K&R a nyelv következő tulajdonságait vezette be:
struct adattípus long int adattípus unsigned int adattípus A =+ típusú értékadó operátorokat a += formára változtatták. (A 'var =- érték' túlságosan hasonlított a 'var = -érték'-hez, bár hatásuk egészen más.)
A K&R C a nyelv legalapvetőbb részének tekinthető, melyet egy C fordítónak mindenképpen ismernie kell. Sok éven keresztül, még az ANSI C bevezetése után is, a „legnagyobb közös osztó” volt a K&R, melyet a C programozók használtak, ha a legnagyobb mértékű (forrás szintű) kompatibilitásra volt szükség, hiszen nem minden C fordító támogatta a teljes ANSI C-t és a megfelelően megírt K&R C (forrás)kód megfelelt az ANSI C szabványnak is.
A K&R C megjelenése utáni években, sok „nem hivatalos” kiegészítés látott napvilágot, melyet az AT&T és néhány másik cég fordítói is támogattak.
Ilyen változtatások voltak többek közt:
void típusú függvény és void * adattípus függvények, melyek struct vagy union típusokat voltak képesek visszaadni (return) különböző struktúráknak lehetnek azonos nevű mezői (korábban az összes struktúra összes mezője egy közös névtéren osztozott!) struktúra típusú változók értékadása (korábban ezt csak a memcpy függvénnyel lehetett megtenni) const definíció, az érték írásvédettségéhez szabvány programkönyvtár (library), mely a különböző cégek leggyakrabban támogatott függvényeit tartalmazta felsorolások (enum) az un. „single-precision” (egyes pontosságú) float adattípus
ANSI C és ISO C
Az 1970-es évek vége felé, a C kezdte felváltani a BASIC nyelvet a személyi számítógépeken. Személyi számítógépekre is átültették az 1980-as években, így a C nyelv népszerűsége ugrásszerűen emelkedni kezdett. Ugyanebben az időben Bjarne Stroustrup és társai a Bell Labs-nél elkezdtek dolgozni objektumorientált nyelvi elemek hozzáadásán a C nyelvhez. A nyelv, amit készítettek a C++ nevet kapta, ez ma a legelterjedtebb programozási nyelv a Microsoft Windows operációs rendszereken, míg a C a UNIX világban megőrizte népszerűségét.
1983-ban az Amerikai Nemzeti Szabványügyi Hivatal (angolul: American National Standards Institute, röviden ANSI) megalakította az X3J11 bizottságot, hogy létrehozzanak egy egységes (szabvány) C definíciót. A hosszú és fáradságos folyamat végén 1989-ben elkészült a szabvány (egy évvel az első C++ ANSI szabvány után!) és jóváhagyták mint: ANSI X3.159–1989 „A C programozási nyelv”. A nyelvnek ezt a verzióját nevezik ANSI C-nek. 1990-ben az ANSI C szabványt (néhány apróbb módosítással) átvette a Nemzetközi Szabványügyi Szervezet (angolul: International Organization for Standardization, röviden ISO) mint ISO/EC 9899:1990.
Az ANSI C szabványosítás egyik célja az volt, hogy a K&R C-ből és a nem hivatalos bővítésekből egy egységeset alakítson ki. Belevettek azonban számos új megoldást is, mint például függvény prototípust (a C++ nyelvből) valamint egy jobban alkalmazható (fejlettebb) előfordítót (preprocesszor).
ANSI C-t szinte minden fordító támogat. A legtöbb C kód, mely manapság íródott, az ANSI C-n alapul. Bármilyen program, amely a szabvány C-ben íródott, helyesen működik bármely platformon, amelyen szabványos C létezik. Vannak azonban programok, melyek csak adott platformon vagy adott fordítóval fordíthatók le, a használt nem szabvány függvénygyűjtemények miatt (például grafikus függvények) és vannak olyan fordítók, melyek nem támogatják alapértelmezésben az ANSI C szabványt.
C99
Az ANSI szabványosítási folyamatot követően, a C nyelv viszonylag állandó maradt, míg a C++ fejlődött. Új C verzió, 1995-ben az első normatív kiegészítéssel jött létre, de ezt a változatot ritkán használják. A szabványt átdolgozták az 1990-es években és ebből lett az ISO 9899:1999 1999-ben. Ez a szabvány „C99” néven vált ismertté, majd 2000 márciusában bekerült az ANSI szabványok közé is.
C99 új tulajdonságai, többek közt:
inline függvények változók definiálási helyére vonatkozó szabályai enyhítése (hasonlóképpen, mint C++-ban) új adattípusok, például: long long int, hogy a 32bitről a 64bitre való átállást megkönnyítsék, explicit bool (stdbool.h) és a complex (complex.h) típus. változó méretű tömbök hivatalosan is bevezették az egysoros kommentár jelölést // (a C++-ból) több új függvény, mint például: snprintf() több új „header” állomány, mint például az inttypes.h, amely rögzített méretű integer típusokat definiál: int8_t, int16_t, int32_t, int64_t, illetve ezek előjel nélküli változatait.
Az érdeklődés a C99 új tulajdonságainak támogatásával kapcsolatban eléggé vegyes. Míg GCC (GNU Compiler Collection, korábban GNU C Compiler) és más fordítók támogatják a C99 újdonságait, addig a Microsoft és Borland által forgalmazottak nem, és ez a két cég nem is foglalkozik a C99 jövőbeli támogatásának lehetőségével jelenleg.
C11 2007-ben kezdődött a munka a C sztenderd egy másik revíziójával kapcsolatban, amit informálisan "C1X"-nek hívtak egészen addig, míg hivatalosan is nem publikálták 2011. december 8-án. A C sztenderdek tanácsa elfogadta az ajánlásokat az új lehetőségek limitált beépítésére, amelyeket még nem kezdtek el tesztelni létező implementáción.
A C11 sztenderd számos új lehetőséget adott hozzá a C és könyvtárakhoz, beleértve a típus generikus makrókat, anonim struktúrákat, javított Unicode támogatást, atomi operációkat, többszálúságot és határ ellenőrző függvényeket. Továbbá elkészítették a létező C99 könyvtár néhány portolását, és javították a kompatibilitást a C++-szal.
C18 A C18-at 2018 júniusában adták ki, ami a C programozási nyelv aktuális szabványa. Nem vezetett be új nyelvi elemeket, csak technikai korrekciókat, pontosításokat tartalmaz a C11-hez képest. Az __STDC_VERSION__ macro 201710L-nek van definiálva.
Beágyazott C Rendszerint a beágyazott rendszerekhez nem szabványosított kiterjesztéseket használnak, hogy lehetővé tegyék az egzotikusabb funkciók használatát, mint pl. fix pontos aritmetikát, különböző memória bankok használatát és alap I/O műveleteket.
2008-ban a C szabványügyi bizottság publikált egy technikai beszámolót, hogy kiterjessze a C programozási nyelvet ezekkel a lehetőségekkel, az által, hogy közös szabványt biztosít. Ez rengeteg funkciót foglal magába ami nem része a normál C-nek, mint pl. fix pontos aritmetika, nevesített címtartományok és alapvető I/O hardver címzések.
A C nyelv jellemzői strukturált szabványos: minden platformon van fordítóprogramja, a kód a forrásprogram szintjén hordozható a C-program rendkívül hatékony gépi kódra fordul le.
A nyelv makrónyelv abban az értelemben, hogy a C-fordító assembly nyelvre fordít, a programozónak azonban egyetlen assembly sort sem kell leírnia (sőt, nem is kell tudnia erről).
A C strukturált programnyelv: bármelyik utasítás helyén állhat blokk, mely { és } jelek közé zárt tetszőleges típusú és számú utasításból állhat. A blokkok egymásba skatulyázhatók. A függvények utasításai blokkban helyezkednek el. A C-program belépési pontja a main nevű függvény, mely az operációs rendszertől kapja a híváskor megadott paramétereket, és annak adja vissza az (egész típusú) visszatérési értékét.
Formai szabályok
A nyelv utasításai a preprocesszor-utasítások kivételével szabad formátumúak: ahol egy helyköz megengedett, ott akárhány helyköz, tabulátor, új sor lehet. A nyelv szavai (utasításnevek, változónevek, számok, műveleti jelek stb.) között lehet helyköz, de nem kötelező. Az utasítások pontosvesszővel végződnek. Az üres utasítás az előző utasítás vége után tett pontosvessző. A folytatósor – a sor végi \ – a szabad formátum miatt csak preprocesszor-utasításokban használatos.
A megjegyzéseket (kommenteket) /* és */ közé kell zárni, és szabvány szerint nem ágyazhatók egymásba, bár sok fordítóprogram mégis megengedi. Az ANSI C-től kezdve használható a //, mely a sor végéig tartó megjegyzést vezet be (a C++-hoz hasonlóan). Hosszabb megjegyzéseket a #if 0...#endif közé is lehet tenni; ezek – lévén preprocesszor-utasítások – egymásba ágyazhatók.
C-ben a nevek kis- és nagybetűkből, számjegyekből és aláhúzásból állhatnak, számjegy nem lehet az első karakter. A kis- és nagybetűk különbözőnek számítanak. A kialakult szokás szerint a változó- és függvénynevekben kisbetűket használunk, a preprocesszor-utasításokban rendszerint nagybetűket.
Utasítástípusok preprocesszor utasítások deklarációk aritmetikai utasítások vezérlő utasítások függvények
A preprocesszor utasítások az assembly nyelvek makróihoz hasonlítanak: a fordítás első menetében „normál” C-utasításokká fordulnak le.
Az aritmetikai utasítások nagyon különböznek a többi programozási nyelvben megszokott értékadó utasításoktól. Ezt az aritmetikai utasítást vette át a C++ és a Java.
A nyelvnek nincs input/output utasítása, ezt szabványos könyvtári függvények végzik.
A végrehajtható utasítások (aritmetikai és vezérlő utasítások) függvényen belül, blokkban helyezkednek el. A C-program preprocesszor-utasításokból, deklarációkból és függvényekből áll.
Egy egyszerű példaprogram #include <stdio.h> // preprocesszor utasítás
int main() // függvénydefiníció, egyúttal a program belépési pontja, ezúttal nincs paramétere { // blokk kezdete int i; // deklaráció
for (i=1; i <= 3; i++) // vezérlő (ciklus-) utasítás. A ++ egyváltozós értékadó művelet: eggyel növeli i-t. { // újabb blokk-kezdet printf("Haho\n"); // I/O műveletet végző könyvtári függvény. A konzolra ír. // A stringkonstansot "-k közé kell zárni. A \n az új sor jele a stringben. } // a belső blokk vége return 0; // vezérlő utasítás: kilépés a függvényből. A main értékét az operációs rendszer kapja meg // Windows-ban az errorlevel, Unixban a $? változóban. } // main blokkjának vége
A program fordítása linuxban (ha a fenti kódot a haho.c file-ba tettük): gcc -o haho haho.c Futtatás: ./haho Kimenet: Haho Haho Haho
A C-programozók a fenti ciklusutasítást for (i=0; i < 3; i++) alakban szokták leírni, mert a tömbök indexelése 0-tól kezdődik a C-ben. A példában a kettő teljesen azonos.
Adattípusok
Egyszerű típusok