C (programspråk)

C är ett generellt, imperativt programspråk. Det tillhör familjen Algol-baserade språk och är avsett för strukturerad programmering.

C är det mest populära programspråket i världen. Det finns C-kompilatorer för nästan alla plattformar, och dess syntax och standardbibliotek har standardiserats av ANSI och ISO. Det har inspirerat och legat till grund för många andra språk, som C++ och Java.

Historia 

Under slutet av 1960-talet började Unix utvecklas ur Multics vid dåvarande Bell Labs (nuvarande AT&T Bell Labs). Dennis Ritchie och Ken Thompson skrev det i makroassembler för minidatorn PDP-7. För att kunna skriva om det i ett högnivåspråk skapade Thompson med Ritchies hjälp programspråket B, en förenklad, minimalistisk version av BCPL anpassad för begränsat minnesutrymme. BCPL är i sin tur en förenklad version av CPL. B introducerade flera syntaktiska egenskaper som återfinns i C, såsom att jämförelser görs med dubbla likamedtecken. B började användas 1969.

B var dock inte ett generellt, plattformsoberoende programspråk. Det var anpassat för den hårdvara som det var skrivet på, PDP-7, och hade bland annat bara en enda datatyp (ordtypen). Ritchie påbörjade därför 1969 utvecklingen av ett nytt språk baserat på B, som han kallade för C, som skulle fungera på såväl mainframedatorer som mini- och mikrodatorer. Den första officiella versionen av Unix kom 1970. Det var då helt skrivet i assembler för PDP-11. Det motiverade än mer utvecklingen av C. Enligt Ritchie skedde den mesta utvecklingen av språket under 1972 och 1973 var det tillräckligt avancerat för att stora delar av Unix kunde skrivas om i det.

I Unix och C:s standardbibliotek anges tidsangivelser vanligen som antal sekunder som har passerat sedan midnatt den 1 januari 1970, så kallad Unix time.

K&R C 
1978 gav Ritchie tillsammans med Brian Kernighan ut den första utgåvan av The C Programming Language, även känd som K&R efter "Kernighan & Ritchie". Boken fungerade länge både som referensverk och som en informell specifikation av språket. De tidiga C-kompilatorerna var inte alltid så strikta med syntaxen, vilket ledde till viss tolkningsfrihet och skillnader mellan olika kompilatorer. Den version av C som introducerades i boken har kommit att kallas för K&R C. Boken använde en formateringsstil, det vill säga regler för var man för läsbarhet sätter mellanslag och radbrytningar i källkoden, som lever kvar än i dag, bland annat i källkoden till Linux.

K&R C introducerade flera standardbibliotek, bland annat det för in- och utdata som i stort är oförändrat än i dag. Boken introducerade även datatyperna "long int" och "unsigned int", samt ett entydigt sätt att skriva kortformer av tilldelning och operation på.

Den andra utgåvan av boken kom 1988. Den behandlar det standardiserade ANSI C, som är mycket striktare i syntaxen.

ANSI och ISO C (C89/C90/C95) 

Under slutet av 1970-talet och början av 1980-talet skrevs C-kompilatorer för ett stort antal mainframedatorer, minidatorer och mikrodatorer. Dessa var inte alltid kompatibla med varandra. 1983 skapade ANSI en kommitté kallad X3J11 med målet att skapa en specifikation för C. Den ratificerades den 7 december 1989 som ANSI X3.159-1989 "Programming Language C". Denna variant av C refereras oftast till som ANSI C eller C89. Året därpå antogs ANSI C som ISO-standard med namnet ISO/IEC 9899:1990. Denna version kallas ibland C90, och är i praktiken identisk med C89.

Redan under arbetet med att anta ANSI C som ISO-standard lades nya förslag fram på utökningar och förbättringar. Eftersom behovet av en färdig standard var trängande togs dessa förslag inte upp för behandling. I stället behandlades de separat och samlades i ett tillägg som lades fram i september 1994 och antogs året därpå som ISO/IEC 9899:1990/Amd 1:1995. Detta tillägg kallas Normative Addendum 1, Amendment 1 eller C95.

ANSI C inkluderar många av de utökningar av språket som hade skett under årens gång. Dessutom lades några nya egenskaper till, bland annat funktionsprototyper och void-pekare. Vissa förbättringar kom från C++. I samband med detta infördes krav på att kompilatorn skulle kontrollera typerna på parametrar till funktioner. Innan C89 gjordes detta inte (externa funktioner deklarerades int my_func();), något som gjorde att en del ansåg C inte vara ett högnivåspråk.

Fortfarande flera år efter ratificeringen av ANSI C ansågs K&R C vara den minsta gemensamma nämnare som programmerare använde för att maximera kodens kompatibilitet med olika plattformar och kompilatorer.

C99 

1999 kom en ny specifikation, ISO/IEC 9899:1999, vanligen kallad C99. C99 introducerade bland annat inline-funktioner, nya datatyper (long long int och complex) och officiellt stöd för radkommentarer som börjar med //, en syntaktisk funktion som fanns i BCPL och C++, och som redan stöddes av många C-kompilatorer.

C99 är mestadels bakåtkompatibel med C90, men är striktare i vissa avseenden. En funktionsdeklaration som saknar returtyp antas inte längre returnera en integer.

Stödet för C99 hos C-kompilatorer är ännu 2012 bristfälligt; många kompilatorer stöder stora delar, men få stöder allt. Bland de få som har fullt stöd finns IBM C.

C11 

2007 påbörjades arbetet med en ny standard under det informella arbetsnamnet C1X. Den antogs i december 2011 som ISO/IEC 9899:2011, vanligen kallad C11. En stor nyhet i C11 var införandet av ett bibliotek för trådning samt stöd i språket för trådsäkra variabler och operationer.

Till följd av att stödet för C99 var så dåligt bland implementationer gjordes vissa delar av C11-standarden frivilliga att implementera, även sådana som är obligatoriska i C99. Ett exempel är stödet för komplexa typer, som är frivilligt i C11 men ett krav för C99-kompatibilitet. För att testa i fall en kompilator har stöd för komplexa typer och biblioteket <complex.h> kan man testa om makrot __STDC_NO_COMPLEX__ är definierat.

C18 

Den senaste standarden antogs 2018 som ISO/IEC 9899:2018, vanligen kallad C18. Denna version introducerade egentligen inget nytt, utan bestod uteslutande av korrigeringar och errata.

Arvet från C 
Att C utvecklades hand i hand med Unix gav det en mycket stark ställning inom Unix-världen, vilken det behåller än i dag. C är alltjämt mycket använt i exempelvis GNU och Linux. C blev tidigt det dominerande språket för utveckling på Microsoft Windows-plattformen, men trängdes ut av först C++ (via programbiblioteket Microsoft Foundation Classes), Delphi och Visual Basic, och sedermera C#.

För inbyggda system har C alltjämt en mycket stark ställning och för många hårdvarunära tillämpningar och realtidssystem är C fortfarande det dominerande språket. Starkt bidragande är att C-kompilatorer finns tillgängliga för de flesta plattformar. C har fördelen för hårdvarunära programmering att man har en rik flora olika heltalstyper och att man kan konvertera pekare ganska fritt.

Relaterade språk 
C är grund för flera andra moderna programspråk. I början av 1980-talet utvecklade Bjarne Stroustrup det objektorienterade språket C++, där konstruktioner hämtade från Simula 67 har lagts till C. Det är delvis, men inte fullständigt, bakåtkompatibelt med C så att vissa program går att kompilera både som C och C++. C++ har i sin tur använts som grund för språk som Java och C#, som dock inte är bakåtkompatibla med vare sig C eller C++.

Objective-C är ett annat objektorienterat programspråk baserat på C, med influenser från Smalltalk. Det är till skillnad från C++ fullständigt bakåtkompatibelt med C, så att källkod skrivet i C kan kompileras med en Objective-C-kompilator.

Syntax och uppbyggnad 
C är skiftlägeskänsligt, det vill säga det skiljer på versaler och gemener i nyckelord och namn så att getvalue, getValue och GetValue är olika namn. Av praxis används versaler sällan utom i preprocessordirektiv och konstanter.

Satser och block 
Varje sats i C är ett kommando som avslutas med ett semikolon, ;. I de flesta fall kan en sats bytas ut mot ett block av kod som inleds med en startklammerparentes, {, och avslutas med en slutklammerparentes, }.

Satser och block behöver inte vara på separata rader. Flera satser kan stå på samma rad och en sats kan vara utspridd över flera rader. Whitespace, det vill säga radbrytningar, tabulatorer och mellanslag, behandlas i de flesta fall lika och behövs bara mellan nyckelord och namn. Denna frihet ger möjligheten till olika kodformateringsstilar, varav en av de mest kända är den som Kernighan och Ritchie använde i The C Programming Language, den så kallade K&R-stilen.

Det främsta undantaget från whitespace-friheten är preprocessordirektiven, som måste stå först på raden och avslutas med en radbrytning eller en kommentar.

Programflöde 
Satserna i C exekveras sekventiellt, uppifrån och ner. Programflödet kan styras med villkorssatser, slingor och ovillkorliga hopp.

Det främsta sättet att göra villkorliga satser på är med if. if följs av ett logiskt uttryck inom parentes, och sedan en sats eller ett block som exekveras om och endast om det logiska uttrycket är sant. Detta kan valfritt följas av else och en sats eller ett block som exekveras om och endast om det logiska uttrycket är falskt. Som komplement till if i situationer där en och samma variabel jämförs med flera värden finns switch-satsen, motsvarande det som i vissa andra språk kallas case-satsen. Den tar ett numeriskt uttryck inom parentes och jämför resultatet med en lista av utfall. Utfallen skrivs med case före och ett kolon efter, och fungerar ungefär som radetiketter. Kodexekveringen fortsätter från respektive rad. Till skillnad från switch- och case-satser i en del andra språk stannar exekveringen inte när nästa case börjar. Vill man lämna switch-satsen använder man break (eller, om man vill avbryta hela funktionen, return). Om ingen matchande case finns fortsätter exekveringen från default om det finns, annars hoppas satsen över.

C har tre olika sorters slingor som också styr programflödet: for, while och do while. for används vanligen för att iterera genom ett antal element, till exempel en lista, med hjälp av en räknare. Till for-satsen hör en tilldelning av en räknare, ett villkor för att avbryta slingan, och en uppräkning av räknaren. while är en enklare slinga än for. Den följs av en parentes med endast ett villkor. do while fungerar precis som while, förutom att villkoret inte testas före första exekveringen; do while-slingan är därför garanterad att exekveras åtminstone en gång.

En slinga kan avbrytas i förtid med nyckelordet break. Exekveringen fortsätter då direkt efter slingan. Om programmet nästlar flera nivåer av slingor är det den närmaste som avbryts. Det går också att hoppa över resten av koden och fortsätta till nästa varv i slingan med nyckelordet continue. I for-slingor exekveras inkrementeringen, och i samtliga slingor testas villkoret. break och continue ger ovillkorliga hopp i programflödet. C tillhandahåller också goto, men det används i praktiken mycket sparsamt. Med goto kan man hoppa till en valfri plats i koden. Denna plats identifieras med ett namn, en radetikett, och avslutas med ett kolon. Till de ovillkorliga hoppen räknas också return, som avslutar eller avbryter en funktion, eventuellt med ett returvärde.

Funktioner 
Funktioner är en av de grundläggande byggstenarna i C. En funktion definieras i C med ett funktionsnamn, en returtyp, ett antal parametrar, samt ett kodblock. Om returtypen är void betyder det att funktionen inte har något returvärde, vilket motsvarar det som i andra programspråk kallas subrutin eller procedur. Funktioner med ett returvärde avslutas med nyckelordet return och returvärdet. Funktioner utan returvärde kan också avslutas med return, alternativt när slutet av kodblocket har nåtts.

En funktionsdeklaration innehåller funktionsnamn, returtyp och vanligen parametrar, men till skillnad från funktionsdefinitionen inget kodblock. Funktioner bör vara antingen deklarerade eller definierade för att C-kompilatorn ska kunna veta hur den ska anropas. Av historiska skäl är det tillåtet att deklarera en funktion utan att ange dess parametrar. Innan ANSI-standarden kom 1989 var det inte möjligt att ange dessa alls, och för att inte ogiltigförklara all C-kod som redan fanns tillät man det gamla skrivsättet. Det är inte vanligt och heller inte rekommenderat. För att skilja funktioner med noll parametrar från funktioner med okända parametrar använder man void som parameterlista.

En funktion kan anropas från ett ställe där den inte redan är definierad, till exempel tidigare i samma källkodsfil, i en annan källkodsfil eller förkompilerad i ett programbibliotek, genom att den deklareras. Denna deklaration sker vanligen i en headerfil som kan inkluderas från alla källkodsfiler som vill använda funktionen.

main 

/* Den typiska deklarationen av main. */
int main(int argc, char **argv);

Varje C-program måste enligt standarden innehålla en funktion som heter main. Det är i main som programmet startar (programmets entry point). Funktionen tar antingen ingen eller två parametrar. De två parametrarna, om de används, innehåller de argument som har skickats till programmet från den anropande miljön: argc (argument count) är ett heltal som säger hur många argument som har skickats med, och argv (argument vector) är en lista av strängar med argumenten. Den första strängen i listan är alltid namnet på programmet självt, vanligen inklusive sökvägen. Funktionen main returnerar ett heltal som typiskt fungerar som resultat eller felmeddelande till den anropande miljön.

Det är tillåtet för system att använda en annan startfunktion. Detta är kompilator- och systemberoende. I Microsoft Windows används vanligen funktionen WinMain, som tar andra parametrar än main.

Kommentarer 
Kommentarer är fritext som en utvecklare kan lägga till källkoden, till exempel för att beskriva vad koden gör. Kommentarer påverkar inte programmet som sådant. En vanliga användning av kommentarer är också att maskera kod så att den inte kompileras med i programmet, vanligen i avlusningssyfte. Detta kallas ofta för bortkommentering av källkod. Kommentarer rensas bort internt av kompilatorn innan källkoden kompileras.

Kommentarer inleds med /* och avslutas med */. Detta kallas ibland för blockkommentarer för att skilja dem från radkommentarer, då de kan användas för att skriva kommentarer över flera rader.

Många C-kompilatorer erbjuder radkommentarer. Dessa startar med // och avslutas vid radbrytning. Denna typ av kommentarer fanns i BCPL men togs inte med i B och heller inte i Ritchies ursprungliga version av C eller i ANSI C. C++ tog däremot upp bruket, och i och med att många kompilatorer fungerar för både C och C++ spred sig bruket till C. Radkommentarer standardiserades i C99.

Preprocessorn 
Preprocessorn är en del av kompileringen av ett C-program. Preprocessorn modifierar källkoden innan den kompileras, genom att följa preprocessordirektiv och expandera makron.

Preprocessordirektiv inleds i C med #, som måste stå först på raden, och avslutas vid radbrytning. Bland de vanligaste direktiven finns #include, som används för att hämta källkod från andra filer, vanligen så kallade headerfiler som innehåller funktionsdefinitioner, makron och andra definitioner. Makron definieras med #define. C-kompilatorn tillhandahåller vissa fördefinierade makron, såsom vilken C-standard som används, det nuvarande filnamnet och radnumret, samt nuvarande tid och datum.

Preprocessorn kan genom direktiv som #if och #else användas för att inkludera viss kod endast under vissa omständigheter. Det kan användas för att inkludera vissa funktioner endast om kompilatorn indikerar att den stödjer viss funktionalitet. Till exempel kan ett miniräknarprogram ges stöd för komplexa tal under villkoret att kompilatorn har definierat makrot __STDC_IEC_559_COMPLEX__. Källkod som exkluderas på detta vis kompileras inte, och kan därför innehålla uttryck och referenser som skulle ge felmeddelanden ifall den hade inkluderats.

Variabler och datatyper 
C har ett antal datatyper. Storlekarna på dem är avsiktligt vagt definierade. Därför kan det vara svårt att porta källkod från ett system till ett annat, till exempel från ett 16-bitarssystem till ett 32-bitarssystem. För att delvis råda bot på det finns sedan C99 en headerfil stdint.h där heltalstyper med garanterade minsta eller exakta storlekar är definierade.

Heltal 
C har fem heltalsdatatyper. Den minsta är char, som representerar teckendata. Storleken på en char är den minsta adresserbara dataenheten som är minst 8 bitar stor, men den kan vara större om systemet kräver det. Superdatorn CDC Cyber kan som exempel inte adressera data mer noggrant än 60 bitar, vilket därmed är storleken på char. I C-standarden definieras detta som en byte, och alla andra datatypers storlekar räknas i multipler av char.

För de flesta heltalsberäkningar används int, som vanligen är samma storlek som datorns ordtyp, typiskt 16 (garanterad minsta storlek), 32 eller 64 bitar. Ibland används varianter av int för data som behöver mer eller mindre utrymme. Datatypen short eller short int är minst 16 bitar, och long eller long int är minst 32, ofta 64 bitar. Sedan C99 finns även long long eller long long int, som är minst 64 bitar.

Heltalstyperna kan modifieras för att begränsa dem till att vara bara positiva, eller att tillåta både positiva och negativa tal. Det påverkar ett program främst vid multiplikation och division, samt vid konvertering mellan olika datatyper. signed innebär att en bit avsätts för att skilja mellan negativa och positiva tal, oftast (men inte nödvändigtvis) i tvåkomplementsform, medan unsigned innebär att alla bitar räknas positivt. Om ingen av dessa två anges så impliceras signed för int-typerna. För char varierar implementationen mellan olika kompilatorer. Enligt standarden är char, signed char och unsigned char tre olika datatyper med samma storlek.

Logiska/booleska värden 
I C fanns ursprungligen ingen strikt boolesk typ, vars enda värden skulle vara sant och falskt. I stället används heltal av typen int, där värdet noll representerar falskt och ett (eller icke-noll) representerar sant. Alla logiska operationer (till exempel jämförelser) returnerar int, och alla villkorliga satser och logiska operatorer tolkar noll som falskt och alla andra värden som sant.

I C99 introducerades typen _Bool, med aliaset bool definierad som ett makro i headerfilen stdbool.h, som en boolesk typ som kan anta värdena noll och ett för falskt respektive sant. Logiska operatorer är dock fortsatt av typen int för att vara bakåtkompatibla med gammal C-kod.

Flyttal 
Det finns tre flyttalstyper i C: float, double och long double. Standarden specificerar inte vad det ska vara för format på de olika typerna – den garanterar över huvud taget inte att det är någon skillnad alls mellan dem, bara att double är minst lika stor som float, och att long double är minst lika stor som double, samt att konvertering till en större typ inte ska ändra värdet på ett tal. I de flesta implementationer är float och double baserade på IEEE 754:s standarder för enkel (32 bitar) och dubbel (64 bitar) precision. Den största flyttalstypen, long double, definierades först i C89. Dess implementation varierar mer mellan olika plattformar, från 64 till 128 bitar.

I standardbiblioteken användes ursprungligen endast double; float behandlades som en minnessparande typ som konverteras till double vid funktionsanrop. I C99 infördes varianter av standardbibliotekens funktioner för float och long double; till exempel fick sinusfunktionen double sin(double) varianterna float sinf(float) och long double sinl(long double).

Komplexa tal 
I C99 definierades en utökning för flyttal för att representera komplexa tal. Dessa definieras med nyckelordet _Complex plus en flyttalstyp. Vanligen används makrot complex, som är ett alias för _Complex men som bara finns tillgängligt om headerfilen complex.h har inkluderats. I samma headerfil finns konstanten I (stora i) definierad som den imaginära enheten. De vanliga flyttalstyperna räknas som reella tal. För rent imaginära tal finns typen _Imaginary på samma sätt som _Complex, med ett motsvarande alias imaginary.

Listor och matriser 

/* En lista med 5 intar. */
int a[5];
/* En matris med 3*4 double. */
double m[3][4];

En lista (engelska: array) definieras genom att till variabelnamnet lägga hakparenteser mellan vilka man skriver listans längd. Längden kan utelämnas om man i definitionen sätter värden på listan. För att läsa eller ändra ett värde i en lista skriver man indexet inom hakparenteser efter variabelnamnet. Det första elementet i en lista har alltid index 0. Rent syntaktiskt kan listan och indexet byta plats; detta används dock sällan i praktiken eftersom det försvårar läsbarheten.

En matris är en lista med två dimensioner, vilket också kan tolkas som en lista av listor. På samma sätt kan man bygga matriser av ännu högre dimensioner.

Förutom vid definitionstillfället kan listor inte tilldelas i sin helhet, bara elementvis.

Pekare 
Pekare är en speciell datatyp som ofta används som exempel på C:s styrka och svaghet. En pekare hänvisar till en adress i minnet där det egentliga datat finns. En pekarvariabel definieras med en datatyp och en asterisk framför pekarnamnet, vilket betyder att pekaren pekar på data av just den datatypen. En pekare kan tilldelas adressen till en annan variabel av motsvarande datatyp genom att man sätter ett et-tecken framför variabeln. För att hämta eller manipulera värdet på den minnesadress som en pekare pekar på skriver man en asterisk framför pekaren.

Pekare är nära besläktade med listor. Listor fungerar väsentligen som konstanta pekare till det första elementet. Pekare kan tilldelas värdet av en listvariabel och användas tillsammans med hakparenteser för att läsa och modifiera listans element. Till en sådan pekare kan ett heltal adderas. Det ger en pekare som pekar på ett annat element i listan. Pekare kan inte adderas till varandra, men differensen mellan två pekare till element i samma lista är avståndet i antal element mellan dem.

En pekare kallas för en nullpekare när den pekar på minnesadressen 0. Detta räknas i princip alltid som att pekaren är oinitierad och inte ännu bör användas. Att försöka att läsa från eller skriva till adress 0 leder i många moderna system till undantag eller att programmet kraschar.

C har friare möjligheter till pekarhantering än många andra programspråk. Det beror på att C utvecklades för programmering av operativsystem med den lågnivåkod det kan innebära. Det går bland annat att typkonvertera mellan olika pekartyper, i synnerhet den "neutrala" pekartypen void *, som bara är en pekare utan datatyp och vars data inte går att läsa utan att typen först specificeras.

Strängar 
Det finns ingen särskilt strängtyp i C, utan en sträng är detsamma som en lista av char-värden, eller en pekare till en sådan lista. Strängar avslutas med ett NULL-tecken, alltså en char med heltalsvärdet 0. När minnesutrymme reserveras för en sträng måste NULL-tecknet räknas med. En sträng kan initieras till en statisk sträng som skrivs inom dubbla citattecken; NULL-tecknet är då implicit med. Det finns inget i strängen som säger hur lång den är, eller hur mycket minne som den kan använda. Den informationen måste beräknas från positionen av NULL-tecknet och kunskap om storleken på listan eller det allokerade minnet.

Strängar kan ses som en av C:s svaga punkter. Eftersom strängar är listor eller pekare går de inte att jämföra som andra variabler, och det går inte heller att utan vidare konkatenera två strängar. I stället används särskilda funktioner i C:s standardbibliotek string.h, som strcmp för jämförelser och strcat för konkatenering. Vid konkatenering måste den mottagande strängen vara tillräckligt stor för att hålla den resulterande strängen, inklusive NULL-tecknet, vilket ställer krav på minneshantering.

void 

void är egentligen ingen datatyp, utan en symbol för när det inte finns någon datatyp. Den används i tre sammanhang:
 Som virtuell returtyp för att deklarera att en funktion inte har något returvärde.
 Som virtuell parameterlista för att deklarera att en funktion inte tar några parametrar.
 För att deklarera eller typkonvertera pekare som typen void *, som kan peka på vilken annan typ som helst.

Sammansatta datatyper 
C har stöd för användardefinierade, sammansatta typer, så kallade strukturer, genom nyckelordet struct. Sammansatta typer består av en eller flera medlemmar som kan vara av olika typer. Det motsvarar vad som i en del andra språk kallas records, eller mycket enkla klasser i objektorienterade språk (men utan stöd för medlemsfunktioner och arv).

En särskilt sorts sammansatta typer är unioner. I unioner pekar alla medlemmar på samma minnesutrymme. Unionens storlek är storleken på den största medlemmen. Det betyder rent praktiskt att det inte går att använda flera medlemmar samtidigt, eftersom de pekar på data som kan betyda helt olika saker beroende på vilken datatyp som förväntas. union kan i kombination med struct användas för att uppnå effekter liknande polymorfism hos objektorienterade språk.

Operatorer 
C har en mängd operatorer för att utföra bland annat matematiska och logiska operationer. En operator har vanligen en eller två operander och returnerar ett värde. Det värdet kan användas i andra operationer, eller till exempel skickas som parameter till en funktion. Detta gäller även operationer som tilldelning: resultatet av b = c är lika med det nya värdet på b. Det värdet kan i sin tur tilldelas en annan variabel: a = b = c. Då tilldelas b värdet av c, och a tilldelas värdet av b = c, det vill säga också c.

Aritmetiska operatorer 
C har stöd för de fyra räknesätten och moduloräkning. Division mellan två heltal är alltid ett heltal. Därför är uttrycket 1/2 alltid lika med noll; för att få ett decimaltal måste ena operanden vara ett flyttal: 1/2.0

En specialare i C är de unära operatorerna för inkrementering och dekrementering, som finns i två former: ett prefix som returnerar det nya värdet och ett suffix som returnerar det gamla. Om b har värdet 5 så gör uttrycket a = b++ att b tilldelas värdet 6 och a värdet 5. I uttrycket a = ++b tilldelas både b och a värdet 6.

Jämförelseoperatorer och logiska operatorer 
Jämförelseoperatorer används för att jämföra två variabler eller uttryck med varandra. Resultatet av en jämförelse är ett heltal av typen int med värdet noll för falskt och ett för sant. Det värdet kan användas aritmetiskt som vilket heltal som helst, men vanligen används det i villkorliga satser eller i logiska uttryck. En egenhet som B introducerade och C ärvde är att likhet testas med dubbla likhetstecken, a == b. Detta för att skilja jämförelse från tilldelning. För att testa olikhet används formen a != b, vilken utläses a är inte lika med b, eller a > b för a är större än b och a < b för a är mindre än b. Det finns också operatorer för att testa om a är större än eller lika med b: a >= b, och vice versa för mindre än eller lika med.

Logiska operatorer används på logiska (booleska) uttryck, vanligen från jämförelser. Det finns bara tre logiska operatorer i C (alla andra varianter kan uttryckas som kombinationer av logiska operatorer och jämförelseoperatorer): negation (ICKE), som skrivs med ett utropstecken före uttrycket, samt konjunktion (OCH) och inklusiv disjunktion (ELLER). Konjunktion och disjunktion skrivs med dubbla tecken (&& respektive ||) för att skilja dem från motsvarande bitoperatorer.

Bitoperatorer 
Bitoperatorer används på heltal för att utföra operationer på binärrepresentationen av tal. Talen hanteras som bitfält. Eftersom C-standarderna inte specificerar hur negativa tal ska representeras är bitoperationer på signed-värden inte nödvändigtvis plattformsoberoende.

Det finns fyra logiska bitoperatorer i C: negation (ICKE), som skrivs med ett tilde (~) före uttrycket, konjunktion (OCH), samt inklusiv (ELLER) och exklusiv (XOR) disjunktion. Konjunktion och disjunktion skrivs med enkla tecken (&, | och ^), vilket skiljer dem från motsvarande logiska operatorer.

C har också operatorer för bitvis skiftning. Uttrycket a << b betyder att a skiftas b steg åt vänster. Skiftningen är inte en rotation, utan nollor skiftas in från höger. Hur högerskiftning av signed-värden hanteras är inte definierat av C-standarderna; en del system skiftar in nollor (logisk skiftning), medan andra skiftar in en kopia på den vänstraste biten (aritmetisk skiftning).

Operatorer för sammansatt aritmetik och tilldelning 

/* Följande uttryck är ekvivalenta. */
a = a * b;
a *= b;

Redan i B fanns möjligheten att utföra en operation på en variabel och tilldela variabeln resultatet med en förenklad syntax. Fördelen är tydligast när vänsterledet är ett komplicerat uttryck, till exempel ett listelement med ett aritmetiskt uttryck som index. Resultatet av uttrycket är detsamma som vid en vanlig tilldelning.

I de första versionerna av C var ordningen på operatorn och likhetstecknet omvänd. Det kunde dock leda till tvetydigheter, eftersom syntaxen blir identisk med den för tilldelning av ett uttryck med en unär operator: i=-10 kunde betyda både i = i - 10 och i = -10. Därför ändrades det i The C Programming Language och i den efterföljande ANSI-standarden.

Operatorer för sammansatt aritmetik och tilldelning finns för alla aritmetiska operatorer (addition, subtraktion, multiplikation, division och modulo), samt för alla bitoperatorer (konjunktion, inklusiv disjunktion och exklusiv disjunktion, samt vänster- och högerskiftning).

Objekt-, pekar- och listoperatorer

Övriga operatorer

Reserverade nyckelord 
C är ett av de språk med lägst antal nyckelord (även kallat reserverade ord): 32 stycken i C89, 37 i C99 och 44 i C11. Nyckelord kan inte användas som namn på variabler, funktioner eller användardefinierade typer.

När namnen på de varibeltyper som introducerades i C99 och C11 skulle bestämmas togs hänsyn till att de kan krocka med användardefinierade typer och variabelnamn i källkod som är skrivna för äldre versioner av standarden. Därför har de fått namn som avviker från mönstret, till exempel _Complex. Genom att inkludera särskilda C99- eller C11-specifika headerfiler fås tillgång till makron med mer typiska namn, till exempel complex.

Många kompilatorer har utöver dessa nyckelord en mindre grupp egna ord för olika kompilatorspecifika funktioner. Ett av de vanligaste är asm, som används för att skriva assemblerkod direkt i C-koden.

Programbibliotek och headerfiler
C har standardiserat ett relativt litet programbibliotek med funktioner för främst in- och utdata, sträng- och minneshantering, samt matematiska funktioner. För att komma åt dem måste de dels länkas in under kompileringen, dels göras tillgängliga genom inkludering av så kallade headerfiler. En headerfil är en källkodsfil med filändelsen .h, som innehåller definitioner av program, datastrukturer, makron och variabler som är externa, det vill säga inte är deklarerade i samma källkodsfil som det program eller de funktioner som använder dem.

Ett exempel är standardfunktionen printf som används för att formatera utskrifter till skärmen. Den är definierad i stdio.h. Själva funktionen finns vanligen i ett förkompilerat programbibliotek som länkas in under kompileringen av ett program. Ett program som vill använda printf måste inkludera stdio.h innan den anropar funktionen, vanligen alldeles i början av källkoden:

#include <stdio.h>

Genom att bara inkludera de headerfiler som behövs och bara länka in de programbibliotek som behövs kan storleken på ett C-program hållas nere.

De flesta kompilatorer tillhandahåller ett antal programbibliotek utöver dem som är standard. Många av dem är mer eller mindre plattformsberoende, till exempel grafiska verktyg och bibliotek för nätverkskommunikation, något som helt saknas i standardbiblioteken.

Lista över headerfiler 
C89 innehåller 15 headerfiler för standardbiblioteket. I tillägget Normative Addendum 1 (NA1) tillkom tre headerfiler. I C99 utökades antalet till 24, och i C11 till 29.

Programexempel 
"Hello, World!" i C:

#include <stdio.h>

int main(void) {
    printf("Hello, world!\n");
    return 0;
}

Primtalsalgoritm för C:

#include <stdbool.h>
#include <math.h>

bool primtal(int n) {
    if (n < 2)
        return false;
    if (n == 2)
        return true;
    if (n%2 == 0)
        return false;
    if (n == 3)
        return true;

    int i = 3;
    int limit = (int)sqrt(n);
    while (i <= limit) {
        if (n%i == 0)
            return false;
        i += 2;
    }

    return true;
}

Se även 
 ANSI C
 C++
 Java
 Objective-C
 Small-C
 C-sharp

Referenser

Externa länkar 

 C