VS | ||
![]() | ||
Ensimmäisen version päivämäärä | 1972 | |
---|---|---|
Paradigma | Pakollinen , menettelyllinen , jäsennelty | |
Kirjoittaja | Dennis Ritchie , Brian Kernighan | |
Kehittäjä | Dennis Ritchie ja Kenneth Thompson, Bell Labs | |
Kirjoittaminen | Staattinen , heikko | |
Standardit | ANSI X3.159-1989 (ANSI C, C89) ISO / IEC 9899: 1990 (C90) ISO / IEC 9899: 1990 / AMD1: 1995 (C95) ISO / IEC 9899: 1999 (C99) ISO / IEC 9899: 2011 ( C11) ISO / IEC 9899: 2018 (C18) |
|
Vaikuttanut | BCPL , B , Algol 68 , Fortran | |
Vaikuttanut | awk , csh , C ++ , C # , Objective-C , D , Samanaikainen C , Java , JavaScript , PHP , Perl | |
Toteutukset | GCC , MSVC , Borland C , Clang , TCC | |
Tiedostotunnisteet | .c, .h | |
Se on yleiskäyttöinen, matalan tason pakollinen ohjelmointikieli . C: stä keksittiin 1970- luvun alussa UNIX: n kirjoittamiseksi , ja siitä on tullut yksi nykyisin eniten käytettyjä kieliä. Monet nykyaikaisemmat kielet, kuten C ++ , C # , Java ja PHP tai Javascript, ovat ottaneet samanlaisen syntaksin kuin C ja ottaneet osittain takaisin sen logiikan. C tarjoaa kehittäjälle huomattavan marginaalin koneen hallintaan (erityisesti muistinhallintaan) ja sitä käytetään siksi näiden nykyaikaisempien kielten "perustusten" (kääntäjien, tulkkien jne.) Rakentamiseen.
C-kielen keksittiin 1972 vuonna Bell Laboratories . Sen kehitti samanaikaisesti UNIXin kanssa Dennis Ritchie ja Kenneth Thompson. Kenneth Thompson oli kehittänyt C: n, B-kielen edeltäjän , joka itse on saanut inspiraationsa BCPL: stä . Dennis Ritchie kehitti B-kielen uudeksi versioksi, joka oli riittävän erilainen, mukaan lukien tyyppien lisääminen , niin että sitä kutsuttiin C: ksi.
Vaikka C on virallisesti B: n ja BCPL: n innoittama, huomataan PL / I: n (tai PL360: n) voimakas vaikutus ; Voisimme sanoa, että C oli Unixille ja PDP-11, mikä PL / I oli Multicsin uudelleenkirjoittamiselle .
Myöhemmin Brian Kernighan auttoi popularisoimaan kieltä C.Se edisti myös muutamia viime hetken muutoksia.
Vuonna 1978 Kernighan oli C-ohjelmointikielen pääkirjoittaja , joka kuvasi lopulta vakiintuneen kielen; Ritchie oli huolehtinut liitteistä ja esimerkeistä Unixin kanssa. Tätä kirjaa kutsutaan myös "K&R: ksi", ja puhumme perinteisestä C: stä tai C K & R: stä viitatessamme kieleen sillä hetkellä.
Vuonna 1983 The American National Standards Institute (ANSI) muodostivat kieli Standards Committee (X3J11), joka 1989 huipentui ns ANSI C tai C89 (muodollisesti ANSI X3.159-1989) standardia. Vuonna 1990 tämän standardin hyväksyi myös Kansainvälinen standardointijärjestö ( C90, C ISO , muodollisesti ISO / IEC 9899: 1990). ANSI C on K&R C: n kehitys, joka on edelleen erittäin yhteensopiva. Se vie joitain ideoita C ++: sta , erityisesti prototyypin ja tyyppikarsintojen käsitteen.
Välisenä 1994 ja 1996 , ISO työryhmä (ISO / IEC JTC1 / SC22 / WG14) julkaisi kaksi korjauksia ja yhden tarkistuksen C90: ISO / IEC 9899 / COR1: 1994 oikaistun 1 , ISO / IEC 9899 / AMD1: 1995 eheys C ja ISO / IEC 9899 / COR1: 1996 tekninen oikaisu 2 . Näihin melko vaatimattomiin muutoksiin viitataan joskus nimellä C89 tarkistuksessa 1 tai C94 / C95. Kolme otsikkotiedostoa on lisätty, joista kaksi liittyy leveisiin merkkeihin ja toinen määrittelee useita makroja, jotka liittyvät ISO 646 -merkkistandardiin .
Vuonna 1999 kielen uusi kehitys standardoitiin ISO : C99: llä (muodollisesti ISO / IEC 9899: 1999). Uusia ominaisuuksia ovat vaihtelevan kokoiset taulukot, rajoitetut osoittimet, kompleksiluvut, yhdistelmälitraalit, sekalausekkeet lausekkeisiin, rivinvaihtofunktiot , edistynyt liukulukutuki ja C ++ -kommenttien syntaksit. C 99 standardin kirjasto on parannettu kuusi header-tiedostot edellisen standardi.
Vuonna 2011 , ISO ratifioi uuden version standardin: C11 , virallisesti ISO / IEC 9899: 2011. Tämä muutos otettiin mukaan lukien tuki ohjelmointi monisäikeinen , The ilmaisuja vuonna tällaisia yleisiä , ja parempaa tukea Unicode .
Se on välttämätön ja yleiskäyttöinen ohjelmointikieli . Se luokitellaan matalan tason kieleksi siinä mielessä, että jokainen kielen käsky on suunniteltu koottavaksi useiksi koneohjeiksi, jotka ovat melko ennustettavissa muistin käyttöasteen ja laskentakuormituksen suhteen. Lisäksi se tarjoaa joukon kokonaisluku- ja liukulukutyyppejä, jotka on suunniteltu vastaamaan suoraan prosessorin tukemia tietotyyppejä . Lopuksi se käyttää intensiivisesti muistiosoitelaskelmia osoittimen käsitteen kanssa .
Perustyyppien lisäksi C tukee lueteltuja , yhdistettyjä ja läpinäkymättömiä tyyppejä . Se ei kuitenkaan tarjoa mitään toimintoa, joka käsittelee suoraan korkeamman tason objekteja ( tietokonetiedosto , merkkijono , luettelo , hash-taulukko jne.). Näitä kehittyneempiä tyyppejä on käsiteltävä manipuloimalla osoittimia ja yhdistetyyppejä. Kieli ei myöskään tarjoa vakiona olio-ohjelmoinnin tai poikkeusten hallintajärjestelmän hallintaa . Tulo- ja lähtö- ja merkkijonojen hallintaan on vakiotoimintoja , mutta toisin kuin muilla kielillä, ei erityistä operaattoria parantamaan ergonomiaa. Tämän ansiosta vakiotoiminnot on helppo korvata toiminnoilla, jotka on erityisesti suunniteltu tietylle ohjelmalle.
Nämä ominaisuudet tekevät siitä suositun kielen, kun yritetään hallita käytettyjä laitteistoresursseja, konekieli ja kääntäjien tuottama binääridata ovat suhteellisen ennustettavissa. Tätä kieltä käytetään siksi laajalti esimerkiksi mikro-ohjainten sulautettuun ohjelmointiin , intensiivisiin laskelmiin, käyttöjärjestelmien ja moduulien kirjoittamiseen, joissa käsittelynopeus on tärkeää. Se on hyvä vaihtoehto kokoonpanokielelle näillä alueilla, ja siinä on ilmeisemmän syntaksin ja lähdekoodin siirrettävyyden edut . C-kieli keksittiin UNIX- käyttöjärjestelmän kirjoittamiseen , ja sitä käytetään edelleen järjestelmän ohjelmointiin. Siten suurten käyttöjärjestelmien, kuten Windows ja Linux, ydin on kehitetty pääosin C: ssä.
Toisaalta C-ohjelmien kehittäminen, varsinkin jos niissä käytetään monimutkaisia tietorakenteita, on vaikeampaa kuin korkeamman tason kielillä. Suorituskyvyn vuoksi C-kieli vaatii käyttäjää ohjelmoimaan tiettyjä prosesseja (vapauttamaan muistia, tarkistamaan taulukoiden indeksien oikeellisuuden jne.), Joista huolehditaan automaattisesti korkean tason kielillä.
Normaalikirjaston tarjoamat mukavuudet C on yksinkertainen kieli, samoin kuin sen kääntäjä . Tämä tuntuu uuden prosessoriarkkitehtuurin C-kääntäjän kehityshetkellä : Kernighan ja Ritchie arvioivat, että se voitaisiin kehittää kahdessa kuukaudessa, koska "huomaamme, että 80% uuden kääntäjän koodista on identtinen muiden olemassa olevien kääntäjien koodit. "
Se on yksi eniten käytetyistä kielistä, koska:
Sen tärkeimmät haitat ovat:
Hei maailma ohjelmaa tarjotaan esimerkkinä 1978 vuonna C-kielellä , jonka Brian Kernighan ja Dennis Ritchie . " Hei maailma " -ohjelmaa luovan ohjelman luomisesta on sittemmin tullut esimerkki uuden kielen perusteiden näyttämisestä. Täällä on alkuperäinen esimerkki 1 s Edition 1978:
main() { printf("hello, world\n"); }Sama ohjelma ISO-standardin mukaisesti ja nykyaikaisia hyviä käytäntöjä noudattaen:
#include <stdio.h> int main(void) { printf("hello, world\n"); return 0; }C: n syntaksin suunniteltiin olevan lyhyt. Historiallisesti sitä on usein verrattu Pascalin kieleen, joka on myös 1970-luvulla luotu välttämätön kieli . Tässä on esimerkki, jossa on kertoma toiminto :
/* En C (norme ISO) */ int factorielle(int n) { return n > 1 ? n * factorielle(n - 1) : 1; } { En Pascal } function factorielle(n: integer) : integer begin if n > 1 then factorielle := n * factorielle(n - 1) else factorielle := 1 end.Jossa Pascal 7 käyttää avainsanat ( function, integer, begin, if, then, elseja end), C käyttää vain 2 ( intja return).
Lausekkeiden kieliC: n lyhyys ei ole vain syntaksia. Käytettävissä olevien operaattoreiden suuri määrä , se tosiasia, että useimmat lauseet sisältävät lausekkeen, että lausekkeet tuottavat melkein aina arvon ja että testilausekkeissa verrataan testatun lausekkeen arvoa vain nollaan, lisäävät lähdekoodin lyhyyttä.
Tässä on esimerkki kopiomerkkijonofunktiosta - jonka periaatteena on kopioida merkit, kunnes olet kopioinut tyhjän merkin, joka tavallisesti merkitsee merkkijonon lopun C: ssä - annettu C-ohjelmointikieli, 2. painos , s. 106 :
void strcpy(char *s, char *t) { while (*s++ = *t++) ; }Loop whilekäyttää klassista C-kirjoitustyyliä, mikä on auttanut antamaan sille maineen huonosti luettavana kielenä. Lauseke *s++ = *t++sisältää: kaksi osoitinpoikkeamaa ; kaksi osoittimen lisäystä ; tehtävä ; ja osoitettua arvoa verrataan nollaan while. Tällä silmukalla ei ole runkoa, koska kaikki toiminnot suoritetaan while. Mielestämme on välttämätöntä hallita tällaiset merkinnät C: n hallitsemiseksi.
Vertailun vuoksi versio, joka ei käytä lyhytoperaattoreita ja implisiittistä nollavertailua, antaisi:
void strcpy(char *s, char *t) { while (*t != '\0') { *s = *t; s = s + 1; t = t + 1; } *s = *t; }C-muodossa kirjoitettu ohjelma on yleensä jaettu useisiin erikseen koottuihin lähdetiedostoihin .
C-lähdetiedostot ovat tekstitiedostoja , yleensä isäntäjärjestelmän merkkikoodauksessa . Ne voidaan kirjoittaa yksinkertaisella tekstieditorilla . On monia toimittajia, jopa integroituja kehitysympäristöjä (IDE), joilla on erityisiä toimintoja tukemaan C-lähteiden kirjoittamista.
Tarkoituksena on antaa laajennustiedoston nimi .c ja .hlähdetiedostot C. Tiedostoja .hkutsutaan otsikkotiedostoiksi , englanniksi headeriksi . Ne on suunniteltu sisällytettäviksi lähdetiedostojen alkuun ja sisältävät vain lauseita .
Kun tiedosto .ctai .hkäyttää toisessa tiedostossa ilmoitettua tunnistetta .h, se sisältää jälkimmäisen. Yleisesti käytetty periaate on tiedoston kirjoittaminen .hkullekin tiedostolle .cja ilmoitettava tiedostoon .hkaikki tiedoston viemät tiedot .c.
Sukupolvi, joka suoritettavan lähdetiedostoista tehdään useassa vaiheessa, jotka ovat usein automatisoituja työkaluja kuten merkki , SCons tai hakutyökaluista integroitu kehitysympäristö. Lähteestä suoritettavaan tiedostoon on neljä vaihetta: esikääntäminen , kokoaminen , kokoonpano , linkkien muokkaus . Kun projekti .ckäännetään , vain tiedostot ovat osa käännettävien tiedostojen luetteloa. tiedostot .hsisältyvät lähdetiedostoihin sisältyviin esikäsittelydirektiiveihin.
C-esiprosessori suorittaa lähdetiedostoihin sisältyvät ohjeet. Hän tunnistaa heidät siitä, että he ovat rivin alussa, ja kaikki alkavat ristihahmosta # . Joitakin yleisimpiä ohjeita ovat:
Direktiivien suorittamisen lisäksi esiprosessori korvaa kommentit tyhjällä välillä ja korvaa makrot. Loput lähdekoodi lähetetään sellaisenaan kääntäjälle seuraavaa vaihetta varten. Jokainen #includelähdekoodissa oleva on kuitenkin korvattava rekursiivisesti mukana olevalla lähdekoodilla. Siten kääntäjä saa yhden lähteen esikäsittelijältä, joka muodostaa kokoamisyksikön.
Tässä on esimerkki lähdetiedostosta, joka copyarray.hkäyttää klassisesti esiprosessorin direktiivejä:
#ifndef COPYARRAY_H #define COPYARRAY_H #include <stddef.h> void copyArray(int *, size_t); #endif#ifndef, #defineJa direktiivit #endifvarmistaa koodin sisällä käännetään vain kerran, vaikka se on mukana useita kertoja. Direktiivi #include <stddef.h>sisältää otsikon, joka ilmoittaa size_talla käytetyn tyypin .
Käännösvaihe koostuu yleensä kokoonpanokoodin luomisesta . Tämä on intensiivisin vaihe hoidoissa. Sen suorittaa kääntäjä itse. Kutakin kokoamisyksikköä varten hankitaan kokoonpanokielitiedosto.
Tämä vaihe voidaan jakaa alavaiheisiin:
Kielen väärinkäytöksellä kutsutaan kokoamista koko suoritettavan tiedoston muodostusvaihe lähdetiedostoista alkaen. Mutta tämä on vain yksi vaiheista, jotka johtavat suoritettavan tiedoston luomiseen.
Jotkut C-kääntäjät työskentelevät tällä tasolla kahdessa vaiheessa, joista ensimmäinen tuottaa ihanteelliselle virtuaalikoneelle (katso Bytecode tai P-Code ) tarkoitetulle välikielelle käännetyn tiedoston, joka on siirrettävissä alustalta toiselle, toinen muuntaa välikielen kokoonpanossa kieli riippuu kohdealustasta. Muut C-kääntäjät mahdollistavat kokoonpanokielen luomisen, vaan vain välikielellä käännetyn tiedoston , joka tulkitaan tai käännetään automaattisesti natiivikoodina ajon aikana kohdekoneella ( virtuaalikoneella, joka linkitetään lopulliseen versioon) ohjelmoida).
Tämä vaihe koostuu muodostetaan sisältävän tiedoston konekielellä kunkin kokoonpano koodi tiedoston. Objekti tiedostot ovat yleensä laajennus .oon Unix ja .objkehittämiseen välineitä MS-DOS , Windows , VMS , CP / M ... Tämä vaihe on joskus ryhmitelty uudelleen edellisten yksi unionin sisäisen tiedonkulun ilman ohi tiedostot väli- kieli tai kokoonpanokieli. Tällöin kääntäjä luo suoraan objektitiedoston.
Välikoodia generoiville kääntäjille tämä kokoonpanovaihe voidaan myös poistaa kokonaan: se on virtuaalikone, joka tulkitsee tai kääntää tämän kielen alkuperäiseksi konekoodiksi. Virtuaalikone voi olla käyttöjärjestelmän komponentti tai jaettu kirjasto .
Linkittäminen on viimeinen vaihe, ja sen tarkoituksena on yhdistää kaikki ohjelman osat. Eri objektitiedostot ja staattiset kirjastot kootaan sitten yhteen tuottamaan vain yksi suoritettava tiedosto.
Linkityksen tarkoituksena on valita hyödyllisiä koodielementtejä, jotka ovat koottujen koodien ja kirjastojen joukossa, ja ratkaista näiden eri elementtien keskinäiset viitteet, jotta ne voivat viitata suoraan ohjelman suoritukseen. Linkitys epäonnistuu, jos viitatut koodielementit puuttuvat.
ASCII merkki sarja on riittävä kirjoittaa C. On jopa mahdollista, mutta harvinaista, rajoittaa itsensä invariantteihin merkistö ISO 646 -standardin , käyttämällä tilanvaihdot nimeltään trigraph. Tyypillisesti C-lähteet kirjoitetaan isäntäjärjestelmän merkistöillä. On kuitenkin mahdollista, että suorituksen merkistö ei ole lähde.
C isot ja pienet kirjaimet . Valkoisia merkkejä ( välilyönti , sarkain , rivin loppu ) voidaan käyttää vapaasti asettelussa, koska ne vastaavat useimmissa tapauksissa yhtä tilaa.
C89: ssä on 32 avainsanaa, joista viittä ei ollut olemassa K&R C: ssä ja jotka ovat aakkosjärjestyksessä:
auto, break, case, char, const(C89), continue, default, do, double, else, enum(C89), extern, float, for, goto, if, int, long, register, return, short, signed(C89), sizeof, static, struct, switch, typedef, union, unsigned, void(C89), volatile(C89) while.Nämä ovat varattuja termejä, eikä niitä tule käyttää toisin.
Versio C99 lisää viisi:
_Bool, _Complex, _Imaginary, inline, restrict.Nämä uudet avainsanat alkavat isolla kirjaimella, jonka edessä on alaviiva maksimoidakseen yhteensopivuuden olemassa olevien koodien kanssa. Tavalliset kirjaston otsikot tarjoavat aliakset bool( <stdbool.h>) complexja imaginary( <complex.h>).
Viimeisimmässä versiossa C11 esitellään vielä seitsemän uutta avainsanaa samalla tavoin:
_Alignas, _Alignof, _Atomic, _Generic, _Noreturn, _Static_assert, _Thread_local.Vakio-otsikoita <stdalign.h>, <stdnoreturn.h>, <assert.h>ja <threads.h>antaa aliaksia vastaavasti alignasja alignof, noreturn, static_assert, ja thread_local.
C-kieli esikääntäjä tarjoaa seuraavat direktiivit:
#include, #define, #pragma(C89) #if, #ifdef, #ifndef, #elif(C89), #else, #endif, #undef, #line, #error.C-kieli ymmärtää monia tyyppejä ja kokonaislukuja , miehittää enemmän tai vähemmän bittejä . Tyyppikoko on vain osittain standardoitu: standardi asettaa vain pienimmän koon ja pienimmän suuruuden. Pienimmät suuruudet ovat yhteensopivia muiden binaaristen esitysten kanssa kuin kahden täydennys , vaikka tätä esitystä käytetään melkein aina käytännössä. Tämän joustavuuden ansiosta kieli voidaan mukauttaa tehokkaasti monenlaisiin prosessoreihin , mutta se vaikeuttaa C-kielellä kirjoitettujen ohjelmien siirrettävyyttä .
Jokaisella kokonaislukutyypillä on "allekirjoitettu" lomake, joka voi edustaa negatiivisia ja positiivisia lukuja, ja "allekirjoittamaton" muoto, joka voi edustaa vain luonnollisia lukuja . Allekirjoitettujen ja allekirjoittamattomien muotojen on oltava samankokoisia.
Yleisin tyyppi on int, se edustaa sanakonetta.
Toisin kuin monet muut kielet, tyyppi charon kokonaislukutyyppi, kuten mikä tahansa muu, vaikka sitä käytetään yleensä merkkien edustamiseen. Sen koko on määritelmän mukaan yksi tavu .
Tyyppi | Edustuksen vähimmäiskapasiteetti | Vähintään suuruus standardi vaatii |
---|---|---|
char | kuten signed chartai unsigned char, toteutuksesta riippuen | 8 bittiä |
signed char | -127 - 127 | |
unsigned char (C89) | 0 - 255 | |
short signed short |
−32 767 - 32 767 | 16 bittiä |
unsigned short | 0 - 65 535 | |
int signed int |
−32 767 - 32 767 | 16 bittiä |
unsigned int | 0 - 65 535 | |
long signed long |
−2 147483 647 - 2147 483 647 | 32-bittinen |
unsigned long | 0 - 4 294 967 295 | |
long long(C99) signed long long(C99) |
−9 223 372 036 854 775 807 - 9 223 372 036 854 775 807 | 64 bittiä |
unsigned long long (C99) | 0 - 18 446 744 073 709552 000 |
Luetellut tyypit määritellään avainsanan enum.
On olemassa liukulukujen tyyppejä , tarkkuus, siis pituus bitteinä, muuttuja; nousevassa järjestyksessä:
Tyyppi | Tarkkuus | Suuruus |
---|---|---|
float | ≥ 6 desimaalia | noin 10 -37 kohteeseen 10 +37 |
double | ≥ 10 desimaalin tarkkuudella | noin 10 -37 kohteeseen 10 +37 |
long double | ≥ 10 desimaalin tarkkuudella | noin 10 -37 kohteeseen 10 +37 |
long double (C89) | ≥ 10 desimaalin tarkkuudella |
C99 lisättiin float complex, double complexja long double complex, jotka edustavat niihin liittyvien kompleksilukuja .
Kehitä tyypit:
Tyyppi _Boolon standardoitu C99: llä. Kielen aiemmissa versioissa oli yleistä määritellä synonyymi:
typedef enum boolean {false, true} bool;Tyyppi voidedustaa tyhjyyttä, kuten tyhjä funktioparametriluettelo tai funktio, joka ei palauta mitään.
Tyyppi void*on yleinen osoitin: mikä tahansa datanosoitin voidaan muuntaa implisiittisesti mistä ja mihin void*. Se on esimerkiksi vakiotoiminnon palauttama tyyppi malloc, joka varaa muistin. Tämä tyyppi ei sovellu toimintoihin, jotka edellyttävät terävän tyypin koon tuntemista (osoittimien aritmeettisuus, viittaukset).
C tukee tyyppejä, jotka on muodostettu rakenteen käsitteellä . Rakenteen määrittelemiseksi sinun on käytettävä avainsanaa structja rakenteen nimeä. Sen jälkeen jäsenet on ilmoitettava aaltosulkeissa. Kuten mikä tahansa lausunto, puolipiste lopettaa koko asian.
/* Déclaration de la structure personne */ struct Personne { int age; char *nom; };Jos haluat käyttää rakenteen jäseniä, sinun on käytettävä operaattoria ..
int main() { struct Personne p; p.nom = "Albert"; p.age = 46; }Funktiot voivat vastaanottaa viitteitä rakenteisiin. He työskentelevät samalla syntaksilla kuin klassiset osoittimet. Operaattoria ->on kuitenkin käytettävä osoittimessa rakenteen kenttien käyttämiseen. On myös mahdollista jättää osoittimen poikkeama, jotta tätä operaattoria ei käytetä, ja silti käyttää operaattoria ..
void anniversaire(struct Personne * p) { p->age++; printf("Joyeux anniversaire %s !", (*p).nom); } int main() { struct Personne p; p.nom = "Albert"; p.age = 46; anniversaire(&p); }C-versiota edeltävässä C99-versiossa kommenttien oli aloitettava vinoviivalla ja tähdellä ("/ *") ja lopetettava tähdellä ja vinoviivalla eteenpäin. Lähes kaikki modernit kielet ovat käyttäneet tätä syntaksia kirjoittaessaan kommentteja koodiin. Kaikki näiden symbolien välissä on kommentti, mukaan lukien rivinvaihto:
/* Ceci est un commentaire sur deux lignes ou plus */C99-standardi otti haltuunsa C ++: n rivin lopun kommentit, jotka esitettiin kahdella kauttaviivalla ja päättyen rivillä:
// Commentaire jusqu'à la fin de la ligneC: n nykyisten hallintarakenteiden syntaksia käytetään laajalti useilla muilla kielillä, kuten tietysti C ++, mutta myös Java , C # , PHP tai jopa JavaScript .
Kolme päätyyppiä on olemassa:
C: n funktiot ovat komentolohkoja, jotka vastaanottavat yhden tai useamman argumentin ja pystyvät palauttamaan arvon. Jos funktio ei palauta arvoa, käytetään avainsanaa void. Funktio ei voi myöskään vastaanottaa argumentteja. Avainsanaa voidsuositellaan tässä tapauksessa.
// Fonction ne retournant aucune valeur (appelée procédure) void afficher(int a) { printf("%d", a); } // Fonction retournant un entier int somme(int a, int b) { return a + b; } // Fonction sans aucun argument int saisir(void) { int a; scanf("%d", &a); return a; } PrototyyppiPrototyyppi koostuu funktion ja sen parametrien ilmoittamisesta ilman sen muodostavia ohjeita. Prototyyppi päättyy puolipisteeseen.
// Prototype de saisir int saisir(void); // Fonction utilisant saisir int somme(void) { int a = saisir(), b = saisir(); return a + b; } // Définition de saisir int saisir(void) { int a; scanf("%d", &a); return a; }Yleensä kaikki prototyypit kirjoitetaan .h- tiedostoihin , ja toiminnot määritellään .c- tiedostossa .
C-kielistandardi jättää tietyt toiminnot määrittelemättä. Tämän C-ominaisuuden avulla kääntäjät voivat käyttää suoraan prosessorikohtaisia ohjeita , suorittaa optimointeja tai jättää huomiotta tietyt toiminnot, koota lyhyitä ja tehokkaita suoritettavia ohjelmia. Vastineeksi se on joskus aiheuttaa vikoja ja siirrettävyys ja lähdekoodin kirjoitettu C.
Tällaista käyttäytymistä on kolme luokkaa:
C: ssä toteutuksen määrittelemät käyttäytymismuodot ovat ne, joissa toteutuksen on valittava käyttäytyminen ja pidettävä siitä kiinni. Tämä valinta voi olla ilmainen tai standardin antamasta luettelosta. Toteutuksen on dokumentoitava valinta, jotta ohjelmoija tietää sen ja käyttää sitä.
Yksi tärkeimmistä esimerkkeistä tällaisesta käyttäytymisestä on kokonaislukutietotyyppien koko. C-standardi määrittää perustyyppien vähimmäiskoon, mutta ei niiden tarkkaa kokoa. Siten, tyyppi intesimerkiksi, joka vastaa koneen sana , on oltava kooltaan vähintään 16 bittiä . Se voi olla 16-bittinen 16-bittisellä prosessorilla ja 64-bittinen 64-bittisellä prosessorilla.
Toinen esimerkki on allekirjoitettujen kokonaislukujen esitys. Se voi olla kahden komplementti , yksi komplementti tai järjestelmä, jossa on merkkibitti ja arvobitit (en) . Suurin osa nykyaikaisista järjestelmistä käyttää kahden täydennystä, joka on esimerkiksi ainoa, jota GCC tukee edelleen. Vanhat järjestelmät käyttävät muita muotoja, kuten IBM 7090, joka käyttää merkki / arvo-muotoa, PDP-1 tai UNIVAC ja sen jälkeläiset, joista joitain käytetään edelleen nykyään, kuten UNIVAC 1100/2200 -sarja # UNISYS 2200 -sarja ( en) , jotka käyttävät yhden täydennystä.
Toinen esimerkki on negatiivisen allekirjoitetun kokonaisluvun oikea siirtymä. Tyypillisesti toteutus voi valita siirtymän kuten allekirjoittamattomalle kokonaisluvulle tai etenemän merkin merkittävimmän bitin.
Määrittelemätön käyttäytyminenMäärittelemätön käyttäytyminen on samanlainen kuin toteutuksen määrittelemä käyttäytyminen, mutta toteutuksen omaksumaa käyttäytymistä ei tarvitse dokumentoida. Sen ei tarvitse edes olla sama kaikissa olosuhteissa. Ohjelma pysyy kuitenkin oikein, ohjelmoija ei voi vain luottaa tiettyyn sääntöön.
Esimerkiksi parametrien arvioinnin järjestystä toimintokutsun aikana ei ole määritelty. Kääntäjä voi jopa päättää arvioida kahden saman toiminnon kutsun parametrit eri järjestyksessä, jos se auttaa sen optimoinnissa.
Määrittelemätön käyttäytyminenC-standardi määrittelee tietyt tapaukset, joissa syntaktisesti pätevillä rakenteilla on määrittelemätön käyttäytyminen. Standardin mukaan mitä tahansa voi tapahtua: kokoaminen voi epäonnistua tai tuottaa suoritettavan tiedoston, jonka suoritus keskeytetään, tai joka tuottaa vääriä tuloksia, tai jopa joka näyttää toimivan ilman virheitä. Kun ohjelma sisältää määrittelemätöntä käyttäytymistä, määrittelemättömäksi tulee koko ohjelman käyttäytyminen, ei vain virheen sisältävän käskyn käyttäytyminen. Siten virheellinen käsky voi vioittaa paljon myöhemmin käsiteltäviä tietoja, mikä viivästyttää virheen ilmentymistä. Ja väärä käsky voi suorittaa kääntäjän suorittamatta optimointia väärien oletusten perusteella, jopa suorittamatta, mikä johtaa suoritettavaan tiedostoon, joka ei tee lainkaan odotettua.
EsimerkkejäVoimme osoittaa klassisen jakamisen nollalla tai muuttujan moninkertaisen määrityksen samassa lausekkeessa esimerkillä:
int i = 4; i = i++; /* Comportement indéfini. */Voidaan siis ajatella, että tässä esimerkissä iarvo voi olla 4 tai 5 kääntäjän valinnan mukaan, mutta se voi yhtä hyvin olla arvoinen 42 tai tehtävä voi pysäyttää suorituksen tai kääntäjä voi kieltäytyä kokoamisesta. Takuuta ei ole olemassa heti, kun käyttäytyminen on määrittelemätöntä.
Vain muutama esimerkki: null-osoittimen poikkeaminen, taulukon käyttö sen rajojen ulkopuolella, alustamattoman muuttujan käyttö tai ylivuotavat allekirjoitetut kokonaisluvut ovat kaikki määrittelemättömiä. Kääntäjä voi käyttää sitä, että koontiversiota ei ole määritelty joissakin tapauksissa, olettaen, että tapausta ei koskaan tapahdu, ja optimoi koodin aggressiivisemmin. Vaikka yllä oleva esimerkki saattaa tuntua ilmeiseltä, jotkut monimutkaiset esimerkit voivat olla paljon hienovaraisempia ja joskus johtaa vakaviin virheisiin.
Esimerkiksi suuri osa koodista sisältää tarkastuksia suorituksen välttämiseksi rajojen ulkopuolisissa tapauksissa, jotka saattavat näyttää tältä:
char buffer[BUFLEN]; char *buffer_end = buffer + BUFLEN; unsigned int len; /* ... */ if (buffer + len >= buffer_end || /* vérification de dépassement du buffer */ buffer + len < buffer) /* vérification de débordement si len très large */ return; /* Si pas de débordement, effectue les opérations prévues */ /* ... */Ilmeisesti tämä koodi on varovainen ja suorittaa tarvittavat turvatarkastukset, jotta allokoitua puskuria ei ylitetä. Käytännössä viimeisimmät kääntäjien versiot, kuten GCC , Clang tai Microsoft Visual C ++, voivat estää toisen testin ja mahdollistavat ylivuotot. Itse asiassa standardi määrittelee, että objektin osoittimen aritmeettisuus ei voi antaa osoitinta tämän objektin ulkopuolelle. Siksi kääntäjä voi päättää, että testi on edelleen väärä, ja poistaa sen. Oikea tarkistus on seuraava:
char buffer[BUFLEN]; unsigned int len; /* ... */ if (len >= BUFLEN) /* vérification de dépassement du buffer */ return; /* Si pas de débordement, effectue les opérations prévues */ /* ... */Vuonna 2008, kun GCC: n kehittäjät muokkaivat kääntäjää optimoimaan tiettyjä määrittelemättömään käyttäytymiseen perustuvia ylivuototarkistuksia, CERT antoi varoituksen GCC: n uusimpien versioiden käytöstä . Nämä optimoinnit ovat itse asiassa läsnä useimmissa nykyaikaisissa kääntäjissä, CERT on tarkistanut vastuuvapauslausekkeensa vastaavasti.
Joitakin työkaluja on olemassa näiden ongelmallisten koontiversioiden havaitsemiseksi, ja parhaat kääntäjät havaitsevat osan niistä (joskus sinun on sallittava tietyt vaihtoehdot) ja voi merkitä ne, mutta yksikään ei väitä olevansa tyhjentävä.
Standardoitu standardi kirjasto , käytettävissä kaikissa toteutuksissa, sisältää yksinkertaisuus liittyy matalan tason kielellä. Tässä on luettelo joistakin otsikoista, jotka ilmoittavat vakiokirjaston tyypit ja toiminnot:
Standardoitu standardikirjasto ei tarjoa tukea graafiselle käyttöliittymälle , verkolle, sarja- tai rinnakkaisporttien I / O: lle, reaaliaikaisille järjestelmille , prosesseille tai edes edistyneelle virhekäsittelylle (kuten rakenteellisissa poikkeuksissa ). Tämä voisi edelleen rajoittaa sellaisten ohjelmien käytännön siirrettävyyttä, joiden on käytettävä joitain näistä ominaisuuksista, ilman, että olisi olemassa paljon kannettavia kirjastoja, ja korvaamaan tämän puutteen; UNIX- maailmassa tämä tarve johti myös toisen standardin, POSIX .1: n syntymiseen .
Koska C-kieli on yksi eniten käytetyistä ohjelmointikielistä, on luotu monia kirjastoja käytettäväksi C: glibin jne. Kanssa . Usein tietomuotoa keksittäessä on olemassa C-viitekirjasto tai ohjelmisto muodon manipuloimiseksi. Tämä pätee zlib , libjpeg , libpng , Expat , MPEG viite dekooderit , libsocket, jne.
Tässä on joitain esimerkkejä, jotka esittävät hyvin lyhyesti joitain C: n ominaisuuksia. Lisätietoja on WikiBookin "C-ohjelmoinnissa" .
Rakenne int_listedustaa linkitettyjen kokonaislukujen luettelon yhtä osaa . Seuraavia kahta toimintoa ( insert_nextja remove_next) käytetään kohteen lisäämiseen ja poistamiseen luettelosta.
/* La gestion de la mémoire n'est pas intégrée au langage mais assurée par des fonctions de la bibliothèque standard. */ #include <stdlib.h> struct int_list { struct int_list *next; /* pointeur sur l'élément suivant */ int value; /* valeur de l'élément */ }; /* * Ajouter un élément à la suite d'un autre. * node : élément après lequel ajouter le nouveau * value : valeur de l'élément à ajouter * Retourne : adresse de l'élément ajouté, ou NULL en cas d'erreur. */ struct int_list *insert_next(struct int_list *node, int value) { /* Allocation de la mémoire pour un nouvel élément. */ struct int_list *const new_next = malloc(sizeof *new_next); /* Si l'allocation a réussi, alors insérer new_next entre node et node->next. */ if (new_next) { new_next->next = node->next; node->next = new_next; new_next->value = value; } return new_next; } /* * Supprimer l'élément suivant un autre. * node : élément dont le suivant est supprimé * Attention : comportement indéterminé s'il n'y pas d'élément suivant ! */ void remove_next(struct int_list *node) { struct int_list *const node_to_remove = node->next; /* Retire l'élément suivant de la liste. */ node->next = node->next->next; /* Libère la mémoire occupée par l'élément suivant. */ free(node_to_remove); }Tässä esimerkissä kaksi keskeistä toimintoa ovat mallocja free. Ensimmäistä käytetään muistin varaamiseen, sen vastaanottama parametri on allokoitavien tavujen määrä ja se palauttaa varatun ensimmäisen tavun osoitteen, muuten palauttaa NULL. freekäytetään vapauttamaan muisti, jonka on jakanut malloc.