C (programozási nyelv)

A Wikipédiából, a szabad enciklopédiából
(C programozási nyelv szócikkből átirányítva)
C
Paradigma imperatív (eljárások)
Jellemző kiterjesztés .h, .c
Megjelent 1972
Tervező Dennis Ritchie
Fejlesztő Dennis Ritchie & Bell Labs
Típusosság statikus, gyenge
Fordítóprogram GCC, MSVC, Borland C, Watcom C
Megvalósítások Clang, GCC, Intel C, MSVC, Turbo C, Watcom C
Hatással volt rá B (BCPL,CPL), ALGOL 68, Assembly, Pascal
Befolyásolt nyelvek awk, csh, C++, C#, ObjC, BitC, D, Concurrent C, Java, Javascript

A C programozási nyelvet Dennis Ritchie az 1970-es évek elején fejlesztette ki (Ken Thompson segítségével), a UNIX operációs rendszereken való használat céljából. Ma már jóformán minden operációs rendszerben megtalálható, és a legnépszerűbb általános célú programozási nyelvek egyike, rendszerprogramozáshoz és felhasználói program készítéséhez egyaránt jól használható. Az oktatásban és a számítógépes tudományokban is jelentős szerepe van.

Tartalomjegyzék

Történet [szerkesztés]

Korai fejlesztések [szerkesztés]

A kezdeti fejlesztések az AT&T keretein 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 mag 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 mag, mely nem assembly nyelven íródott, korábbiak, a Multics PL/I-ben íródott, a Tripos BCPL-ben.

K&R C [szerkesztés]

1978-ban megjelent a Dennis Ritchie és Brian Kerninghan 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.)

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üggyvénnyel lehetett megtenni)
  • const definíció, az érték írásvédettségéhez
  • szabvány függvény-gyűjtemény (un. 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 [szerkesztés]

Az 1970-es évek vége felé, a C kezdte felváltani a BASIC nyelvet a személyi számítógépeken. IBM PC 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 objektum orientá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 (preprocessor).

ANSI C-t szinte minden használt 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 [szerkesztés]

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 ez a változat ritkán használt). Akárhogyan is, de 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ének 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.

A klasszikus „Helló, világ!” C-ben [szerkesztés]

A következő egyszerű program a „Helló, világ!” szöveget írja ki alapértelmezett kimeneti eszközre, ami általában a képernyő, de lehet egy állomány vagy más is. Ennek a programnak az első változata a K&R-ben jelent meg.

#include <stdio.h>
 
int main(void)
{
   printf("Hello world!\n");
   return 0;
}

A program első sora egy #include utasítás, hatására az előfeldolgozó (preprocesszor) erre a helyre bemásolja a megnevezett állomány tartalmát. Ebben az esetben ez a stdio.h állomány. A hegyes zárójel (kisebb, nagyobb jel, „kacsacsőr”) arra utal, hogy az stdio.h állomány a fordító részére megadott ún. „include path” által definiált helyen van.

A következő nem üres sor a „main” függvény definíciója. A main függvény egy speciális függvény a C programokban, amely a program indításakor legelőször hívódik meg. Az „int” megadja, hogy a „main” függvény egy integer (egész szám) típusú adatot ad vissza. A „void” azt jelenti, hogy a függvény nem vár paramétereket vagy adatokat az őt meghívó rutintól. A kapcsos zárójel a függvény törzsének kezdetét jelzi.

A következő sor „meghívja”, vagy futtatja a printf függvényt. Az „include”-olt állomány, a stdio.h tartalmazza a printf függvény meghívásának leírását („prototípusát”, „deklarációját”). Ebben az esetben, a printf függvényt mindössze egyetlen paraméterrel hívjuk meg, mégpedig egy fix szöveggel („string literal”): „Helló, világ!\n”. A \n új sort jelent. A printf függvény ugyan ad vissza értéket (a kiírt karakterek számát), de ez jelen esetben nem érdekel minket, ezért nem is foglalkozunk vele.

A return utasítás jelenti a kilépést az aktuális függvényből (ami ebben az esetben a main), és megadja a hívónak visszaadandó értéket (esetünkben nullát, ami a program hibátlan lefutását jelzi). (Mivel ebben az esetben az aktuális függvény a main, a hívó maga a programbetöltő program, pontosabban egy olyan speciális könyvtári függvény (tipikus neve: _init), amivel a felhasználói programozónak általában nem kell foglalkoznia). Végül a záró kapcsos zárójellel jelezzük a „main” függvénytörzs végét.

Felépítése [szerkesztés]

C program tartalmaz függvényeket és változókat. A C függvények hasonlítanak a FORTRAN függvényeire (function) és alrutinjaira (subroutine) vagy a Pascal függvényeire (function, procedure). A main() egy speciális függvény, ahol a C program „elkezdődik”, ez azt jelenti, hogy minden C programnak tartalmaznia kell egy main() függvényt.

Általában a main() „meghív” más függvényeket, a feladatok elvégzésére. Vagy a programozó írja ezeket a függvényeket, vagy egy külső függvénygyűjteményből (könyvtár, angolul library) kerülnek ki; az utóbbiak elérhetősége ún. fejléc-állományok (header) beillesztésével biztosítható, az előfordító (preprocessor) #include utasításával. Bizonyos könyvtári függvények, mint a printf() a fenti példában, a C szabvány által definiáltak, ezek a szabvány könyvtárban megtalálható függvények. (Egy olyan C implementációt, amely tartalmaz minden szabványos könyvtári funkciót, „befogadott implementáció”-nak nevezünk. Nem minden implementációban található meg minden függvény, például azért, mert azok nem használhatók az adott operációs rendszeren.) Más könyvtárak plusz lehetőségeket biztosítanak, például grafikus, bonyolult matematikai megoldások valamit az adott platform sajátosságait kihasználó függvények alakjában.

A függvények adhatnak vissza értéket az őt meghívó környezetnek. Emellett azokat a paramétereket, melyeket cím szerint kap meg, szintén meg tudja változtatni.

 void swap(int *a,int *b)
 {
   int tmp;
   tmp = *a;
   *a = *b;
   *b = tmp;
 }
 
 int main()
 {
  int aa = 12;
  int bb = 13;
  swap(&aa,&bb);
 }
 
 //Ezután aa == 13, bb == 12

A main() függvény hívója az operációs rendszer maga. Emiatt, a „Helló, világ!” példában fent, az operációs rendszer 0-t (nulla) kap vissza, amikor a program befejeződik. (A printf függvény visszaadja a kiírt karakterek számát, melyet ebben az esetben figyelmen kívül hagyunk.)

Egy C függvény definíciója tehát a visszaadott érték típusa (void vagy semmi ha nincsen érték), egy egyedi név, a paraméterek listája zárójelben (void ha nincsenek) és a függvény törzse kapcsos zárójelek között.