Programski jezik C

Iz Wikipedije, proste enciklopedije
Skoči na: navigacija, iskanje
C
Text in light blue serif capital letters on white background and very large light blue sans-serif letter C.
Programski jezik C (The C Programming Language)[1] (velikokrat imenovana »K&R«), osnovna knjiga o C-ju
Paradigma imperativna (proceduralna), strukturalna
Začetna izdaja 1972[a]
Oblikoval Dennis Ritchie
Razvijalec Dennis Ritchie & AT&T Bellovi laboratoriji (tvorci);
ANSI X3J11 (ANSI C);
ISO/IEC JTC1/SC22/WG14 (ISO C)
Stabilna izdaja C11 (2011-12-08)
Tipizacija statična, šibka, manifestna, imenska
Večje implementacije GCC, Clang, Intel C, MSVC, Pelles C, Watcom C/C++
Dialekti Cyclone, Unified Parallel C, Split-C, Cilk, C*
Vplivi B (BCPL, CPL), ALGOL 68,[b] zbirni jezik, Speedcoding, PL/I, FORTRAN
Vplival na številne: AMPL, AWK, csh, C++, C--, C#, Objective-C, BitC, D, Go, Rust, java, JavaScript, Limbo, LPC, Perl, PHP, Pike, Processing, Python, Seed7, Verilog (HDL)[3]
OS mnogoplatformsko
Običajna končnica datoteke .c, .h, a.out
Wikibooks logo C Programming na Wikibooks

Prográmski jêzik C ali kar C (izgovorjava [cé] ali po izvirniku [sí], /ˈs/) je nizkonivojski standardizirani računalniški programski jezik tretje generacije (3GL) za splošno rabo, ki ga je prvotno razvil Dennis Ritchie med letoma 1969 in 1973 v AT&T Bellovih laboratorijih.[4][2][5] Ritchie in Ken Thompson sta najprej razvila prevajalnik za operacijski sistem Unix, ki je bil v osnovi napisan v zbirnem jeziku. Unixovo jedro je bilo tako prvo napisano v drugem jeziku in ne v zbirnem. Kasneje se je C hitro pojavil tudi na drugih operacijskih sistemih. Kot večina imperativnih jezikov v tradiciji ALGOLa je C zmožen strukturalnega programiranja in omogoča leksično območje spremenljivk ter rekurzijo, statični sistem tipov pa preprečuje mnogo nenameravanih operacij. Njegova konstrukcija omogoča konstrukte, ki se učinkovito preslikujejo v tipične strojne ukaze, in zaradi tega se je C začel rabiti v aplikacijah, ki so bile prej razvite v zbirnem jeziku, še posebej v sistemskem programju, kot je npr. računalniški operacijski sistem Unix.[6]

C velja za učinkovit jezik in je primeren za sistemska opravila, ni pa najprimernejši za učenje programiranja, čeprav se pogosto pojavlja v izobraževanju. Je tudi eden od najbolj razširjenih programskih jezikov, skupaj z javo, C++ ali PHP, od leta 2008 pa mu priljubljenost celo rahlo narašča.[7][8] Obstaja zelo malo arhitektur in operacijskih sistemov za katere ni na voljo prevajalnika za C. C se veliko rabi tudi za razvoj prenosljive uporabniške programske opreme.[6]

Razvoj jezika C je zelo vplival na druge programske jezike, še posebej na C++, ki se je razvil kot razširitev C-ja. Mnogo kasnejših jezikov si je neposredno ali posredno sposodilo določene gradnike C-ja, na primer: D, Go, Rust, java, JavaScript, Limbo, LPC, C#, Objective-C, Perl, PHP, Python, Verilog (strojni opisni jezik),[3] in Unixova C shell. Ti jeziki so dobili mnogo svojih kontrolnih struktur in drugih osnovnih gradnikov od C-ja. Večina od njih, kjer je Python največja izjema, je tudi skladenjsko podobnih C-ju v splošnem in so usmerjeni na združevanje razpoznavnih izrazov in stavkov skladnje jezika C z osnovo sistemov tipa, podatkovnih modelov in semantiko, ki je lahko popolnoma drugačna. C++ in Objective-C sta bila na začetku jezika prevajalnikov, ki so tvorila kodo v C. C++ je trenutno skoraj supermnožica C,[9] Objective-C pa je stroga supermnožica C.[10][11][12]

Pred uradnim standardom za C se je mnogo uporabnikov in izvršiteljev opiralo na neuradno specifikacijo, opisano v knjigi Programski jezik C Briana Kernighana in Ritchieja. Ta različica je v splošnem znana kot »K&R« C. Leta 1989 je Ameriški državni inštitut za standarde (ANSI) objavil standard za C (v splošnem imenovan »ANSI C« ali »C89«). Naslednje leto je to specifikacijo potrdila Mednarodna organizacija za standardizacijo (ISO) kot mednarodni standard (v splošnem imenovan »C90«). ISO je kasneje izdala razširitev standarda za podporo internacionalizacije leta 1995 in popravljeni standard (znan kot »C99«) leta 1999. Ta standard je do sedaj najbolj razširjen. Trenutna različica standarda (sedaj imenovana »C11«) je ISO kot ISO/IEC 9899:2011 potrdila 8. decembra 2011.[13]

Osnovne značilnosti jezika[uredi | uredi kodo]

C je dokaj skop programski jezik, ki deluje blizu strojne opreme, in je z razliko od večine programskih jezikov bolj podoben zbirniku. Včasih ga imenujejo »prenosljivi zbirnik«, kar tudi označuje njegovo pomembno razliko od zbirniškega jezika. Izvorno kodo, napisano v C, se da prevesti in pognati na skoraj vsakem stroju. Tega ne zmore skoraj noben obstoječ programski jezik in tudi kodo, zapisano v zbirniku, lahko poženemo le na določenih vrstah strojev. C po navadi imenujejo nizkonivojski ali srednjenivojski jezik, kar označuje kako blizu strojne opreme lahko deluje.

C so naredili zaradi enega samega pomembnega namena, kar ni slučajnost, da bi bilo moč pisati velike programe z manj napakami v proceduralnem programiranju in, da pisec programov ne bi nosil bremena tvorjenja prevajalnika za C, ki ga otežujejo zapleteni gradniki jezika. V tem smislu ima C naslednje pomembne značilnosti:

Razvoj[uredi | uredi kodo]

Zgodnji razvoj[uredi | uredi kodo]

Ken Thompson in Dennis Ritchie, tvorca programskega jezika C

Izvor jezika C je tesno povezan z razvojem operacijskega sistema Unix, ki sta ga izvirno razvila v zbirnem jeziku na računalniku DEC PDP-7 Ritchie in Thompson v AT&T Bellovih laboratorijih, in vključila več zamisli svojih kolegov. V začetku Thompson niti ni programiral na samem PDP-7, ampak je rabil množico makrojev za zbirni jezik GEMAP na 32-bitnem osrednjem stroju General Electric GE-635. Nato je poprocesor tvoril papirni trak, ki ga je PDP-7 lahko prebiral.[2] Kmalu je Unix s preprostim jedrom, zbirnim jezikom, preprosto lupino (tolmačem ukazov) in z nekaterimi pripomočki (kot npr. Unixovi ukazi rm, cat, cp) leta 1969 postal samozadosten, in razvoj se je lahko nadaljeval neodvisno na samem PDP-7. Douglas McIlroy je kmalu zatem tvoril prvi visokonivojski jezik sistema Unix, izvedbo prevajalnika prevajalnikov TMG Roberta M. McClurea. McIlroy in Bob Morris sta uporabila TMG za zgodnji prevajalnik jezika PL/I v operacijskem sistemu Multics. Thompson se je zaradi McIlroyjevega uspeha reproduciranja TMG odločil, da je Unix, ki verjetno tedaj še ni bil imenovan tako, potreboval lasten sistemski programski jezik.

Pisanje v zbirnem jeziku novo nastalega Unixa je bilo nerodno. Za pisanje programskih struktur se je porabilo več časa, kodo je bilo težje razhroščevati in jo razumeti.[14] Thomson je želel imeti prednosti visokonivojskega jezika vendar ne v smislu operacijskega sistema Multics, napisanega v PL/I in zbirnem jeziku. Bil je vodja neformalne skupine v AT&T, ki je začela pregledovati možnosti drugih operacijskih sistemov in višjenivojskih jezikov. Najprej je s pomočjo TMG leta 1970 neuspešno hotel uporabiti Fortran[15], nato pa je ustvaril jezik B s poenostavitvijo raziskovalnega jezika BCPL, ki ga je leta 1967 razvil Martin Richards, tako da je lahko njegov tolmač šel v 8 kB 18 bitni besedni pomnilnik računalnika PDP-7.

B se je izkazal za zelo počasnega in nezmožnega za sistemsko programiranje v samem Unixu. Tako kot BCPL je bil brez tipov. Pri novem zmogljivejšem računalniku DEC PDP-11 je bil jezik brez tipov neizvršljiv. Njegov procesor je podpiral podatkovne tipe različnih velikosti in z jezikom B tega ni bilo moč izraziti. Problem je bilo tudi izvajanje. Thompson in Ritchie sta se odločila prenesti operacijski sistem na PDP-11. Tudi njegov operacijski sistem je bil napisan v zbirnem jeziku. Želela sta napisati operacijski sistem v jeziku B. Najprej je zaradi nezmožnosti rabe nekaterih prednosti računalnika PDP-11, še posebej bajtno naslovljivost, v letu 1971 nastal »novi B« (NB), ki je rešil te probleme.[16] Ta jezik se je kmalu razvil in preimenoval (leta 1972) v C. Postal je prevajalni in ne tolmačitveni jezik.

Začetni razvoj jezika C je po Ritchiejevih besedah potekal v AT&T Bellovih laboratorijih med letoma 1969 in 1973[2]. Najbolj kreativno obdobje je bilo leta 1972. Tedaj je bila večina Unixa ponovno napisana v C-ju.[17] Do leta 1973 z dodatkom podatkovnega tipa zapisov struct je C postal dovolj močan za prevod Unixovega jedra. Novi jezik je dobil ime »C«, ker so bili njegovi gradniki izvedeni iz jezika »B«, ta pa je bil po Thompsonovih besedah okleščena različica jezika BCPL.[18]

Tako je bilo Unixovo jedro prvo jedro kakšnega operacijskega sistema napisano v drugem jeziku od zbirnega. Pred tem sta bila na primer še operacijska sistema Multics (napisan v PL/I) in MCP (Master Control Program) za sistem Burroughs B5000 (napisan v ALGOLu leta 1961.) Leta 1977 sta Ritchie in Stephen Curtis Johnson dodatno spremenila jezik C za pospešitev prenosljivosti operacijskega sistema Unix. Johnsonov Portable C Compiler (PCC) je služil kot osnova za več izvedb C-ja na novih platformah.[19]

K&R C[uredi | uredi kodo]

Naslovnica izvirne prve izdaje knjige Programski jezik C (The C Programming Language) iz leta 1978

Leta 1978 sta Kernighan in Ritchie objavila prvo izdajo knjige Programski jezik C (The C Programming Language).[20] Ta knjiga, pri programerjih v C-ju znana kot »bela knjiga« (white book), oziroma »K&R«[2], je bila mnogo let neformalna specifikacija jezika. Različica jezika C, ki ga knjiga opisuje, se navadno imenuje K&R C. Druga izdaja knjige[20] pokriva kasnejši standard ANSI C.

K&R je uvedla nekaj jezikovnih gradnikov:

  • standardna V/I knjižnica
  • podatkovni tip long int
  • podatkovni tip unsigned int
  • sestavljeni prireditveni operatorji v obliki =op (kot npr. =-) so spremenjeni v obliko op= zaradi semantične dvoumnosti pri tvorjenju takšnih konstruktov kot npr. i=-10, kar je bilo tolmačeno kot i =- 10 (zmanjšaj i za vrednost 10) namesto možno predvidenega i = -10 (priredi i vrednost -10)

Tudi po objavi standarda C leta 1989, je K&R C še vedno mnogo let veljal za »najmanjši skupni imenovalec« na katerega so se programerji v C-ju omejili, kadar je bila žaželena največja možna prenosljivost, saj je bilo v rabi še vedno več starejših prevajalnikov, skrbno napisana koda v K$R C pa je bila lahko tudi veljavni standard za C.

V zgodnejših različicah C-ja je bilo treba pred definicijo uvesti le funkcije, ki so vračale vrednosti razen tipov int. Funkcija, ki se je rabila brez predhodne deklaracije, je privzeto vračala vrednosti int, če se je njena vrednost uporabila. Na primer:

long neka_funkcija();
/* int */ druga_funkcija();
 
/* int */ klicna_funkcija()
{
long test1;
register /* int */ test2;
 
    test1 = neka_funkcija();
    if (test1 > 0)
        test2 = 0;
    else
        test2 = druga_funkcija();
    return test2;
}

Označevalce tipa int, ki so izpuščeni, v K&R C ni bilo treba navajati, kasnejši standardi pa so jih zahtevali.

Ker deklaracija funkcij v K&R C ni vsebovala nobenega podatka o parametrih funkcije, njihovo preverjanje ni bilo izvedeno, čeprav je nekaj prevajalnikov javljalo opozorilno sporočilo, če je bila lokalna funkcija klicana z napačnim številom parametrov, ali, če je več klicev zunanje funkcije rabilo različno število tipov parametrov. Razvili so več ločenih orodij, kot na primer Unixov pripomoček lint, ki so poleg drugih stvari lahko preverjala doslednost rabe funkcij križem v več datotekah izvorne kode.

Po objavi K&R C so k jeziku dodali več gradnikov, ki so jih podpirali prevajalniki, na primer od AT&T (še posebej PCC[21]) in od nekaterih drugih ponudnikov. Med njimi so:

Veliko število razširitev, pomanjkanje dogovora o standardni knjižnici, priljubljenost jezika in dejstvo, da tudi na operacijskem sistemu Unix prevajalniki niso dosledno izvrševali specifikacije K&R, je vodilo do potrebe za standardizacijo.

ANSI C in ISO C[uredi | uredi kodo]

Glavni članek: ANSI C.

V poznih 1970-ih in 1980-ih so izvedli različice C-ja za širok razpon osrednjih računalnikov, miniračunalnikov in mikroračunalnikov, vključno z osebnim računalnikom IBM PC, saj se je tedaj njegova priljubljenost zelo povečala.

Leta 1983 je Ameriški državni inštitut za standarde (ANSI) ustanovil odbor X3J11 za ustanovitev standardne specifikacije jezika C. X3J11 je osnoval standard za C na Unixovi izvedbi; vendar so neprenosljivi del Unixove knjižnice C predali delovni skupini 1003 IEEE, ki je postala osnova za standard POSIX leta 1983. Leta 1989 so standard C potrdili kot ANSI X3.159-1989 »Programming Language C«. Ta različica jezika se po navadi imenuje ANSI C, Standard C ali včasih C89.

Leta 1990 je standard ANSI C (z oblikovnimi spremembami) sprejela Mednarodna organizacija za standardizacijo (ISO) kot ISO/IEC 9899:1990, kar se včasih imenuje C90. Tako se izraza »C89« in »C90« nanašata na isti programski jezik.

Kakor druge nacionalne ustanove za standarde ANSI ni več razvijal standarda C neodvisno, ampak ga je odložil k mednarodnemu standardu C, ki ga vzdržuje delovna skupina ISO/IEC JTC1/SC22/WG14. Nacionalna usvojtev posodobitve mednarodenga standarda se po navadi izvede še v letu publikacije ISO.

Eden od ciljev procesa standardizacije jezika C je bilo tvorjenje supermnožice K&R C, ki bi vključevala več predhodno uvedenih neuradnih gradnikov. Standardizacijski odbor je vključil tudi več dodatnih gradnikov, kot so npr. prototipi funkcij (izposojeno od C++), kazalci void, podpora za mednarodni nabor znakov in lokalnih parametrov, ter predprocesorske izboljšave. Čeprav je bila skladnja za deklaracijo parametrov povečana, da bi vključevala slog rabljen v C++, je bil vmesnik K&R zaradi združljivosti z obstoječo izvorno kodo še naprej dovoljen.

C89 podpirajo trenutni prevajalniki za C, večina kode v C-ju, ki je zapisana sedaj, temelji na njem. Vsak program, zapisan le v ANSI C in brez privzetkov odvisne strojne opreme, se bo izvajal pravilno na katerikoli platformi v skladu z izvedbo C-ja v mejah svojih virov. Brez takšnih previdnosti se lahko programi prevedejo le na določenih platformah ali z določenim prevajalnikom zaradi na primer rabe nestandardnih knjižnic, kot so knjižnice grafičnih uporabniških vmesnikov, ali oslonitev na računalniške ali specifične platformske atribute, kot je točna velikost podatkovnih tipov in ureditev bajtov (endianness).

V primerih, ko mora biti koda prevedljiva tako v skladu s standardom ali s prevalniki na osnovi K&R C, se lahko rabi makro __STDC__, ki razdeli kodo na dele z ANSI C in K&R, ter tako prepreči prevajalnikom na osnovi K&R C uporabo gradnikov, razpoložljivih le v ANSI C.

Po standardizacijskem procesu ANSI/ISO je specifikacija jezika C več let ostala statična. Leta 1995 so k standardu C iz leta 1990 dodali Normative Amendment 1 (ISO/IEC 9899/AMD1:1995, neformalno znan kot C95). Z njim so popravili nekaj podrobnosti in dodali obsežnejšo podporo mednarodnega nabora znakov.

C99[uredi | uredi kodo]

Glavni članek: C99.

Standard C so v poznih 1990-ih na novo popravili, kar je leta 1999 vodilo do objave standarda ISO/IEC 9899:1999, ki je v splošnem znan kot »C99«. Od tedaj so ga s tehniškimi popravki dopolnili trikrat.[22]

C99 je uvedel več novih gradnikov. Na primer znotrajvrstične funkcije (inline functions), nove podatkovne tipe (na primer long long int in complex za delo s kompleksnimi števili), polja s spremenljivo dolžino (variable-length arrays (VLA)), izboljšano podporo aritmetike s plavajočo vejico IEEE 754, podporo variarnih makrojev (variadic macros, makrojev s spremenljivo arnostjo) in podporo enovrstičnih komentarjev, ki se začnejo z dvema poševnicama //, kot v BCPL ali C++. Več teh gradnikov je kot razširitve tedaj že podpiralo nekaj prevajalnikov za C.

C 99 je večinoma nazaj združljiv s C90, vendar je na nekaterih mestih strožji. Še posebej, deklaracija, ki je brez specifikatorja tipa, implicitno privzeto ni več tipa int. Standardni makro __STDC_VERSION__ je določen z vrednostjo 199901L in nakazuje, da je na voljo podpora C99. GCC, Solaris Studio in drugi prevajalniki za C sedaj podpirajo mnogo ali pa vse nove gradnike C-ja v standardu C99. Prevajalnik za C v Microsoft Visual C++ izpolnjuje standard C89 in tiste dele C99, ki so zahtevani za združljivost z različico standarda C++11.[23]

C11[uredi | uredi kodo]

Leta 2007 so se začela dela na novi različici standarda C, ANSI C11 ali ISO/IEC 9899:2011, do objave 8. decembra 2011 neformalno imenovane »C1X«. Standardizacijski odbor je sprejel smernice za omejitev usvojitve novih gradnikov, ki jih niso preskusili z obstoječimi izvedbami.

V standardu C11 se je pojavilo več novih gradnikov jezika C in knjižnic, na primer: makroji rodovnih tipov, anonimne strukture, izboljšana podpora kodirnega standarda Unicode, atomske operacije, mnogonitnost in funkcije s preverjanjem mej. Neketeri deli obstoječe knjižnice C99 so postali izbirni, izboljšana je bila tudi združljivost s C++.

Vdelani C[uredi | uredi kodo]

Glavni članek: vdelani C.

Programiranje z vdelanim C-jem (embedded C) zgodovinsko zahteva nestandardne razširitve k jeziku C, da se lahko podpirajo C-ju tuji gradniki, kot so npr.: aritmetika s fiksno vejico, mnogokratne različne pomnilniške vrstice in osnovne V/I operacije.

Leta 2008 je standardizacijski pododbor SC 22 objavil tehniško poročilo z razširitvijo jezika C,[24] ki se je nanašala na probleme med razširitvami jezika C za različne vdelane sisteme, in tako zagotovila splošni standard za vse ustrezne izvedbe. Vključuje več gradnikov, ki v normalnem C niso na voljo: aritmetika s fiksno vejico, prostori z imenovanimi naslovi in osnovno V/I naslavljanje strojne opreme.

Vdelani C rabi večino skladnje in semantike standardnega C-ja: funkcija main, definicija spremenljivk, deklaracija podatkovnih tipov, pogojni stavki (if, switch, case), zanke (while, for), funkcije, polja in znakovni nizi, strukture in unije, bitne operacije, makroji ipd.

Skladnja[uredi | uredi kodo]

Glavni članek: skladnja jezika C.

C ima formalno slovnico, ki jo določa standard C.[25] Z razliko od nekaterih drugih jezikov, kot je npr. FORTRAN 77, je izvorna koda C-ja proste oblike, kjer se znaki za prazni prostor lahko rabijo poljubno, koda pa ni odvisna od stolpčnih ali besedilno-vrstičnih omejitev. Komentarji so lahko med razmejilnima znakoma /* in */ enovrstično ali mnogovrstično, od standarda C99 naprej pa tudi za razmejilnima znakoma // enovrstično do konca vrstice. Komentarji, ki jih razmejujeta /* in */, ne smejo biti vgnezdeni. Če se zaporedje teh dveh znakov pojavi znotraj znakovnega niza ali znakovnega črkovnega simbola, se ne obravnavata kot razmejilna znaka komentarja.[20] Komentarji oblike:

/* ... */
 
/*
...
*/
 
/* ... // ... */
 
// ...
 
/*
... // ...
*/

so v redu, vgnezdeni enovrstično pa npr. ne:

/* /* ... */ ... */

ali vgnezdeni mnogovrstično:

/* 
/* ... 
*/ ... 
*/

saj drugo zaporedje /* ne velja za razmejilni znak komentarja, kot tudi ne drugo zaporedje */, ki je sedaj zunaj komentarja, in prevajalnik bi v obeh primerih javil napako.

Datoteke s C-jevsko izvorno kodo vsebujejo deklaracije in definicije funkcij. Definicije funkcij po vrsti vsebujejo deklaracije in stavke. Deklaracije definirajo nove podatkovne tipe z rezerviranimi besedami, kot so: struct, union in enum, ali prirejajo tipe in morda rezervirajo pomnilniška mesta novim spremenljivkam, po navadi z zapisom tipa, ki mu sledi ime spremenljivke. Rezervirane besede, kot sta char in int, označujejo vgrajene tipe. Deli kode so obdani z zavitima oklepajema { in }, ki omejujeta deklaracijsko področje ali pa delujeta kot samostojni stavek za kontrolne strukture.

Nabor znakov[uredi | uredi kodo]

Osnovni nabor znakov izvorne kode jezika C vsebuje:

Nova vrstica označuje konec vrstice besedila. Ni treba da odgovarja dejanskemu posameznemu znaku, čeprav je v C zaradi prikladnosti to posamezen znak.

Lahko se rabijo tudi dodatni mnogobitno zakodirani znaki v prikazu znankovnih nizov, vendar niso povsem prenosljivi. Zadnji standard za C (C11) dovoljuje mnogonacionalne znake kodirnega standarda Unicode, ki so prenosljivo lahko del besedila izvorne kode C s pomočjo kodiranj \uXXXX ali \UXXXXXXXX, kjer X označuje šestnajstiško zapisan znak. Ta možnost še ni v široki rabi.

Osnovni izvršni nabor znakov C obsega enake znake, skupaj s prikazom opozorila (alert), povratnega znaka (backspace) in pomika na začetek vrstice (carriage return). Podpora izvajalnemu času za razširjene nabore znakov se je z vsako različico standarda za C povečevala.

Rezervirane besede[uredi | uredi kodo]

Naslednje besede (keywords; reserved words) so v jeziku C rezervirane in imajo strog pomen kot posamezni znaki (tokens).[26][13] Ne smejo se na novo opredeliti ali se rabiti kot identifikatorji v drugih kontekstih:

_Alignas
_Alignof
_Atomic
auto
_Bool
break
case
char
_Complex
const
continue
default
do
double
else
enum
entry
extern
float
for
_Generic
goto
if
_Imaginary
inline
int
long
_Noreturn
register
restrict
return
short
signed
sizeof
static
_Static_assert
struct
switch
_Thread_local
typedef
union
unsigned
void
volatile
while[27]

Besede so občutljive na male ali velike črke. INT, INt, InT, Int, iNT, iNt ali inT na primer ni enako kot int. V različnih izvedbah prevajalnikov za C se lahko pojavijo tudi druge rezervirane besede, npr. ada, asm, fortran, pascal, čeprav se tam običajno nestandardne besede začnejo z enim ali dvema podčrtajema, npr. __asm, _Cdecl ipd.[27] V primerjavi z drugimi velikimi jeziki ima C majhno število rezerviranih besed. Ada jih ima na primer 62. Ena od značilnosti jezika C je, da lahko naredi veliko z relativno malo posebnimi simboli in rezerviranimi besedami.[26] Na začetku je imel C manj rezerviranih besed, na primer 29, sedaj pa jih pozna 44. Kasneje so bile dodane rezervirane besede, kot so: _Bool, _Complex, const, _Imaginary, inline, restrict, signed in volatile. Beseda entry se ni nikoli rabila in sedaj ni več rezervirana.[20]

Oblika programa in slog v C[uredi | uredi kodo]

Osnovni gradnik programa v C je funkcija.[28] Vsak program v C je zbirka ene ali več funkcij. Funkcije sestavljajo deklaracije spremenljivk in stavki, ali zapleteni ukazi, obkrožata pa jih zavita oklepaja ({ in }).

Zgleda programov[uredi | uredi kodo]

Program PozdravljenSvet[uredi | uredi kodo]

Spodnji zgled izpiše znakovni niz »Pozdravljen svet!« na standardni izhod. Navadno je standardni izhod povezan z zaslonom monitorja, lahko pa je tudi datoteka ali kakšna druga strojna naprava. Program je napisan v skladu s standardom ANSI C.

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

Sledi analiza programa po vrsticah:

#include <stdio.h>

Prva vrstica v programu je predprocesorski ukaz (navodilo, direktiva) #include. Pred samim prevajanjem programa predprocesor pregleda izvorno kodo in izvrši vse predprocesorske ukaze. Ti ukazi se vedno začnejo z znakom #. Ukaz #include povzroči, da se na njegovo mesto v izvorno kodo vključi datoteka stdio.h, ki vsebuje standardne vhodno izhodne funkcije.

int main(void)

V naslednji vrstici se definira funkcija z imenom main. Ta funkcija ima poseben pomen v C programih. Pri začetku izvajanja programa se najprej kliče ta funkcija. Ključna beseda int na začetku vrstice pove, da funkcija main() vrne celo število, ključna beseda void pa, da funkcija ne sprejme nobenih parametrov. Funkcija main po standardu ANSI C vedno vrača vrednost, čeprav nekateri prevajalniki prevedejo kodo uspešno, četudi temu ni tako. Tudi v jeziku C++ je ta funkcija še vedno C-jevska. Funkcija main je lahko definirana s pomočjo naslednjih štirih oblik ob deklaraciji:[29][c][d]

int main() { /* ... */ }
int main(void) { /* ... */ }
int main(int argc, char *argv[]) { /* ... */ }
int main(int argc, char **argv) { /* ... */ }

oziroma prototipno:

int main();
int main(void);
int main(int, char *[]);
int main(int, char **);

Prvi dve definiciji sta enakovredni (in združljivi s C++).

{

Odprti zaviti oklepaj pomeni začetek definicije main funkcije.

printf("Pozdravljen svet!\r\n");

V tej vrstici se kliče funkcija printf, ki je deklarirana v datoteki stdio.h. Pri tem klicu se funkciji printf poda en parameter v obliki znakovnega niza. Na koncu znakovnega niza je še posebni dvoznakovni niz \n, ki se prevede v znak EOL (end of line). Znak je namenjen kot ukaz izhodni napravi, da postavi trenutno lego na začetek naslednje vrstice.

return 0;

Vrstica zaključi izvajanje main funkcije in vrne celo število 0.

}

Zaprti zaviti oklepaj pomeni zaključek definicije funkcije main.

Minimalni program[uredi | uredi kodo]

Katera definicija funkcije main se uporabi v programu, je verjetno odvisno od posamezne izbire. Trenutni standard C vsebuje dva zgleda rabe main() in dva main(void), standard C++ pa rabi main(). Vrednost, ki jo main vrača (in mora biti tipa int), služi kot status prekinitve. Tega program vrne gostiteljevemu okolju.

Standard C definira vrnitveni vrednosti 0 (»nič napak« (zero errors)) in EXIT_SUCCESS, ki označujeta uspeh, ter EXIT_FAILURE za označevanje neuspešnega zagona programa. (EXIT_SUCCESS in EXIT_FAILURE sta definirani v standardni zaglavni datoteki stdlib.h). Druge vrnitvene vrednosti služijo kot izvedbeni definicijski pomeni. V Linuxu na primer program, ki ga je prekinil ukaz signal, vrne kodo številske vrednosti signala plus 128.

Minimalen pravilen program v C vsebuje prazno funkcijo main brez parametrov:

int main(void){}

Lahko se zapiše tudi v več vrsticah:

int main(void)
{          /* začetek telesa funkcije v prvem stolpcu vrstice */
}

ali redkeje sicer v skladu z dobrim slogom:

int         /* podatkovni tip vrnjene vrednosti funkcije */
main(void)  /* ime funkcije v prvem stolpcu vrstice */
{           /* začetek telesa funkcije v prvem stolpcu vrstice */
}

Sploh pa je slaba praksa pisati neporavnano, kot npr:

int
    main
        /*
            ** 
* *   * **/ (
        void
    )
{ }

ali:

    int
   main/*
 ** * *  * 
**/(void){ }

oziroma poravnano brez reda:

int    main    /*
**     *       *
***/   (       void
)      {       }

Preveden program bo sicer deloval, izvorna koda pa je že v preprostem zgledu nepregledna. Seveda je treba rezervirane besede, imena spremenljivk in funkcij pisati brez presledkov.

Okrogla oklepaja (), ki sledita imenu funkcije, morata biti vključena, saj na ta način C razlikuje funkcije od navadnih spremenljivk. Načeloma pri funkcijah za imenom funkcije in odprtim oklepajem ni presledka, npr. main(void) in ne main (void), z razliko od sizeof (), ki dejansko strogo ni funkcija, in je skladenjska rezervirana beseda za enočleni operator.[30] sizeof je lahko podobno kot return brez okroglih oklepajev. Pri return je to celo zaželeno, razen če je dvoumno.

Ker nista navedena return ali exit, funkcija main ob izhodu vrne 0.[31] To je poseben primer predstavljen v standardu C99, ki velja le za funkcijo main. Če se zahteva še ta navedba, ima minimalni program obliko:

int main(void) { return 0; }

Funkcija main bo za uspešno delovanje programa po navadi klicala druge funkcije. Ni treba, da je na vrhu programa, tako da se program v C ne začne v prvi vrstici, ampak tam kjer je navedena funkcija main.[28] Funkcije main ni možno klicati ali jo zagnati s kakšno drugo funkcijo v programu. Kliče jo lahko le operacijski sistem in na ta način se zažene program v C.

Nekatere izvedbe niso izvedljive, po navadi zaradi tega, ker niso mišljene za rabo z operacijskim sistemom. Takšne izvedbe se v standardu C imenujejo prostostoječe (free-standing). V prostostoječi izvedbi ni podrobnega opisa kako naj obravnava zagon programa. V programu še posebej ni treba definirati funkcije main.

Druge funkcije se lahko imenujejo poljubno v skladu s skladnjo jezika. Lahko jih napiše programer sam ali pa se rabijo obstoječe iz knjižnic. Vmesniki za knjižniške funkcije so običajno navedeni z vključitvijo zaglavnih datotek s preprocesorsko direktivo #include, objekti knjižnice pa se povežejo v končno izvršno sliko. Določene knjižniške funkcije, kot sta na primer printf ali scanf, so definirane s standardom C, in se imenujejo standardne knjižniške funkcije.

Funkcija lahko vrne vrednost klicatelju - po navadi drugi funkciji C-ja, ali gostiteljevemu okolju za funkcijo main. Zgoraj omenjena funkcija printf vrne koliko znakov je bilo izpisano, vendar se ta vrednost običajno prezre.

Podatkovni tipi[uredi | uredi kodo]

C ima statični šibki sistem tipov, ki je deloma podoben potomcem ALGOLa, kot je npr. paskal, vendar C sam ni potomec Algola.[32] V C obstajajo vgrajeni tipi za cela števila različnih velikosti, tako predznačena in nepredznačena, števila s plavajočo vejico (npr. racionalna števila), znake in naštevalne tipe (enum). C99 je z rezervirano besedo _Bool dodal Booleov podatkovni tip (Booleova spremenljivka). Obstajajo tudi izpeljani tipi, kot so: polja (tabele, arrays), kazalci, zapisi (struct) in nenaznačene unije (union).

C se velikokrat rabi v programiranju nizkonivojskih sistemov, kjer morda ni potrebe za sistemom tipov. Prevajalnik poskuša zagotoviti pravilnost tipov večine izrazov, vendar lahko programer zaobide preverbe na več načinov, ali s pomočjo opustitve tipov (type cast), kjer ekscplicitno pretvori vrednost iz enega tipa v drugega, ali s pomočjo kazalcev ali unij, kjer se osnovni biti podatkovnega objekta na novo tolmačijo na kakšen drug način.

Za nekatere je deklaracijska skladnja v C neintuitivna, še posebej kazalci na funkcije. (Richiejeva zamisel je bila, da se označevalci deklarirajo v kontekstu njihove rabe: »deklaracija zrcali rabo.«)[20]

C-jevske običajne aritmetične pretvorbe dovoljujejo tvorjenje učinkovite kode, vendar lahko včasih pride do nepričakovanih rezultatov. Primerjava predznačenih in nepredznačenih celih števil enale širine na primer zahteva pretvorbo predznačene vrednosti v nepredznačeno. To lahko povzroči nepričakovane rezultate, če je predznačena vrednost negativna.

Osnovni tipi[uredi | uredi kodo]

V jeziku C je več osnovnih podatkovnih tipov. Večina od njih se tvori iz enega od štirih osnovnih aritmetičnih označevalcev tipov v C (char, int, float in double), ter štirih izbirnih označevalcev (signed, unsigned, short in long). Vsi razpoložljivi osnovni aritmetični tipi so navedeni v razpredelnici:

podatkovni tip
in sopomenke
pojasnilo
char najmanjša naslovljiva enota stroja, ki lahko vsebuje osnovni nabor znakov. Njen tip je celoštevilski. Dejanski tip je lahko predznačen ali nepredznačen, kar je odvisno od izvedbe.
signed char enaka velikost kot char, vendar je zagotovo predznačena.
unsigned char enaka velikost kot char, vendar je zagotovo nepredznačena.
short
short int
signed short
signed short int
predznačeni celoštevilski tip short. Njegov obseg je vsaj [−32767, +32767],[33] in zato je njegova velikost vsaj 16 bitov.
unsigned short
unsigned short int
enako kot short, vendar nepredznačeno.
int
signed int
osnovni predznačeni celoštevilski tip. Njegov obseg je vsaj [−32767, +32767],[33] in zato je njegova velikost vsaj 16 bitov.
unsigned
unsigned int
enako kot int, vendar nepredznačeno.
long
long int
signed long
signed long int
predznačeni celoštevilski tip long. Njegov obseg je vsaj [−2147483647, +2147483647],[33] in zato je njegova velikost vsaj 32 bitov.
unsigned long
unsigned long int
enako kot long, vendar nepredznačeno.
long long
long long int
signed long long
signed long long int
predznačeni celoštevilski tip long long. Njegov obseg je vsaj [−9223372036854775807, +9223372036854775807],[33] in zato je njegova velikost vsaj 64 bitov. Uveden s standardom C99.
unsigned long long
unsigned long long int
enako kot long long, vendar nepredznačeno. Uveden s standardom C99.
float tip za števila s plavajočo vejico in enojno točnostjo. Dejanske značilnosti niso navedene (razen spodnjih mej), vendar je na večini sistemov to dvojiški format števila s plavajočo vejico in enojno točnostjo IEEE 754. Ta format zahteva izbirni Annex F »IEC 60559 floating-point arithmetic.«
double tip za števila s plavajočo vejico in dvojno točnostjo. Dejanske značinosti niso navedene (razen spodnjih mej), vendar je na večini sistemov to dvojiški format števila s plavajočo vejico in dvojno točnostjo IEEE 754. Ta format zahteva izbirni Annex F »IEC 60559 floating-point arithmetic.«
long double tip za števila s plavajočo vejico in razširjeno točnostjo. Dejanske značilnosti niso navedene. Z razliko od tipov float in double je lahko 80-bitni format s plavajočo vejico, »double-double«, ki ni v skladu z IEEE ali dvojiški format števila s plavajočo vejico in štirikratno točnostjo IEEE 754, če je format s povišano točnostjo zagotovljen, drugače je enako kot double. Za podrobnosti glej članek o long double.

Dejanska velikost celoštevilskih tipov se v izvedbah razlikuje. Standar zahteva le velikostne povezave med podatkovnimi tipi in najmanšimi vrednostmi za vsak podatkovni tip:

Zahteve za povezave so, da long long ni manjši od long, ki ni manjši od int, ta pa ne manjši od short. Ker je velikost char vedno najmanjši podprti podatkovni tip, vsi drugi podatkovni tipi ne morejo biti manjši.

Najmanjša velikost za char je 8 bitov, najmanjši velikosti za short in int sta 16 bitov, za long 32 bitov in za long long mora vsebovati vsaj 64 bitov.

Tip int mora biti celoštevilski tip, za katerega je ciljni procesor najbolj učinkovit. To omogoča veliko prilagodljivost, saj so lahko na primer vsi tipi 64-bitni. Vendar je priljubljeno več različnih shem celoštevilskih širin (podatkovnih modelov). To je zato ker podatkovni model definira kako različni programi med seboj komunicirajo, enotni podatkovni model se rabi znotraj uporabniškega vmesnika danega operacijskega sistema.[34]

Treba je omeniti, da je v praksi velikost tipa char po navadi 8 bitov, tipa short pa 16 bitov (kakor tudi njihova nepredznačena dvojnika). To velja za platforme pogoste v 1990-ih, kot so: SunOS 4 Unix, Microsoft MS-DOS, sodobni Linux in Microchip MCC18 za vdelane 8-bitne mikrokontrolerje PIC. POSIX zahteva, da je velikost char točno 8 bitov.

Tudi dejanska velikost in obnašanje tipov s plavajočo vejico se razlikuje v izvedbah. Edino zagotovilo je, da long double ni manjši od double, ki ni manjši od float. Če ju strojna oprema podpira, se po navadi rabita 32-bitna in 64-bitna dvojiška formata s plavajočo vejico IEEE 754.

Glej tudi[uredi | uredi kodo]

Opombe[uredi | uredi kodo]

  1. ^ »Thompson je na kratko leta 1972 poskusil tvoriti sistem v zgodnji različici C-ja pred strukturami, vendar je prenehal.«[2]
  2. ^ »Shema sestavljanja tipov, ki jih je privzel C, dolguje veliko jeziku Algol 68, čeprav se morda ni pojavil v obliki, ki bi jo potrdili privrženci Algola[2]
  3. ^ Standard ISO C (razdelek 5.1.2.2.1) zahteva veljavnost obeh oblik funkcije main, brez parametrov: int main() oziroma: int main(void), ali z dvema parametroma: int main(int argc, char *argv[]), kar je izjema le za to funkcijo.
  4. ^ V nekaterih operacijskih sistemih, še posebej v starejših različicah Unixa, ima lahko funkcija main tri parametre v obliki:
    int main(int argc, char *argv[], char *envp[]) { /* ... */ }
    

    kjer je tretji parameter kazalec na vektor predvsem imen spremenljivk okolja. Tretji parameter envp v funkciji main pa ni v skladu s standardom POSIX in se podatki o obstoječih spremenljivkah okolja pridobivajo z drugimi funkcijami, na primer getenv. Prevajalnik gcc za Linux na primer to možnost podpira.

Sklici[uredi | uredi kodo]

  1. ^ Kernighan; Ritchie (1978).
  2. ^ 2,0 2,1 2,2 2,3 2,4 2,5 Ritchie (1993).
  3. ^ 3,0 3,1 "Verilog HDL (and C)". The Research School of Computer Science at the Australian National University. 2010-06-03. Pridobljeno dne 2013-08-19. "1980s: ; Verilog prvič predstavljen ; na Verilog je vplival programski jezik C" 
  4. ^ Stewart (2000).
  5. ^ Giannini; Code Fighter, Inc.; Univerza Columbia (2004), str. 164.
  6. ^ 6,0 6,1 Lawlis (1997).
  7. ^ "Programming Language Popularity" (v angleščini). 2009. Pridobljeno dne 2009-01-16. 
  8. ^ "TIOBE Programming Community Index" (v angleščini). 2009. Pridobljeno dne 2009-05-06. 
  9. ^ Stroustrup (1993).
  10. ^ "Write Objective-C Code" (v angleščini). apple.com. 2013-04-23. Pridobljeno dne 2013-12-22. 
  11. ^ Dawkins (2006).
  12. ^ Lee (2013).
  13. ^ 13,0 13,1 "WG14 N1570 Committee Draft — April 12, 2011" (v angleščini). Pridobljeno dne 2014-10-13. 
  14. ^ Van der Linden (1994).
  15. ^ Ritchie (1979).
  16. ^ "History of C". cppreference.com (v angleščini). 2014-08-19. Pridobljeno dne 2014-11-0. 
  17. ^ Stallings (2012), str. 91.
  18. ^ "A Brief History of C" (v angleščini). 
  19. ^ Johnson; Ritchie (1978).
  20. ^ 20,0 20,1 20,2 20,3 20,4 Kernighan; Ritchie (1988).
  21. ^ Stroustrup (2002).
  22. ^ "JTC1/SC22/WG14 – C". Domača stran (v angleščini). ISO/IEC. Pridobljeno dne 2011-06-02. 
  23. ^ Binstock (2011).
  24. ^ "TR 18037: Embedded C" (v angleščini). ISO / IEC. Pridobljeno dne 2011-07-26. 
  25. ^ Harbison; Steele (2002).
  26. ^ 26,0 26,1 Kelley; Pohl (1984), str. 61.
  27. ^ 27,0 27,1 "C Language Reference" (PDF). openwatcom.org (v angleščini). Pridobljeno dne 2010-12-31. 
  28. ^ 28,0 28,1 "The form of a C program". The GNU C Programming Tutorial (v angleščini). Pridobljeno dne 2014-10-10. 
  29. ^ "WG14 N1256 Committee Draft — September 7, 2007: 5.1.2.2.1 Program startup" (v angleščini). Pridobljeno dne 2014-10-13. 
  30. ^ Larson (1996b).
  31. ^ Klemens (2014).
  32. ^ Feuer; Gehani (1982).
  33. ^ 33,0 33,1 33,2 33,3 ISO/IEC 9899:1999 specification, TC3. str. 22, § 5.2.4.2.1 Sizes of integer types <limits.h>. 
  34. ^ "64-Bit Programming Models: Why LP64?" (v angleščini). The Open Group. 1997. Pridobljeno dne 2011-11-09. 

Viri[uredi | uredi kodo]

Zunanje povezave[uredi | uredi kodo]


Glavni programski jeziki (več)

Industrijski: ABAP | Ada | C | C++ | C# | COBOL | Delphi | Fortran | java | JavaScript | lisp | Objective-C | Perl | PHP | PL/SQL | Python | SAS | sh | SQL | Visual Basic | zbirnik

Akademski: Eiffel | Haskell | Logo | ML | paskal | prolog | scheme | Smalltalk

Zgodovinski: ALGOL | APL | AWK | BASIC | Clipper | PL/I | Simula