Med en variabel i C menas ett lagringsutrymme som har getts ett namn. I lagringsutrymmet kan man förvara exempelvis ett heltal eller en textsträng. Det som finns i lagringsutrymmet kallas för variabelns värde.
Vi kommer ofta att tala om lagringsutrymmet som ett gömställe; värdet som finns där betraktar vi som en skatt. Detta är naturligtvis en smula barnsligt, något jag ber läsaren ha överseende med eftersom det kommer att hjälpa oss att bättre förstå hur variabler fungerar.
Man måste i förväg tala om för C vilken typ av värde variabeln ska ha. Detta kallas för att deklarera variabeln. Följande program använder en heltalsvariabel:
#include <stdio.h>
int main(int argc,char *argv[])
{
int tal;
tal=5;
printf("Talet har värdet %d.\n",tal);
return 0;
}
Raden int tal; deklarerar tal
som en heltalsvariabel (int).
Satsen tal=5; ger
variabeln tal värdet 5.
Eller, med vår terminologi, en skatt på 5 miljoner
kronor lagras i ett gömställe med namnet tal.
Likhetstecknet ska alltså läsas som ''tilldelas värdet''.
Syntaxen för textsträngen i printf ovan
är något besynnerlig.
Mellan citationstecknen
har vi med %d angett att ett heltal ska stoppas
in på den platsen, och efter kommat anges
vilket heltal det är som ska stoppas in där.
Antag att programmet ovan är sparat under namnet
heltal.c.
Vid kompileringen vill vi att det körbara programmet
ska heta heltal snarare är a.out.
Detta anges med flaggan -o till gcc.$ gcc -o heltal heltal.c
$ heltal
Talet har värdet 5.
$Ett variabelnamn som står till vänster om ett
likhetstecken syftar på lagringsutrymmet,
inte på värdet som finns lagrat där
(dvs på gömstället, inte på skatten).
Likhetstecknet kallas för tilldelningsoperatorn.
Satsen tal=5; betyder alltså ''lagra talet 5 i
lagringsutrymmet med namnet tal''.
I andra sammanhang, dvs när tal inte står till vänster
om en tilldelningsoperator, är det underförstått
att namnet tal syftar på det värde som lagras i variabeln
(dvs det syftar på skatten, inte på gömstället).
Ett exempel på detta är att tal såsom
argument till funktionen
printf tolkades som talet 5.
Ändra nu programmet ovan till följande:
#include <stdio.h>
int main(int argc,char *argv[])
{
int tal;
printf("Ange ett tal: ");
scanf("%d",&tal);
printf("Talet har värdet %d.\n",tal);
return 0;
}
Instruktionen scanf("%d",&tal) läser in ett heltal
och tilldelar variabeln
tal detta heltal som värde.
Kompilera om programmet och prova:$ gcc -o heltal heltal.c
$ heltal
Ange ett tal: 34
Talet har värdet 34.
$Observera tecknet & före tal ovan.
Det är inte särskilt lätt
att förklara varför tecknet behövs,
men vi försöker ändå: scanf ska läsa in ett heltal
och lagra det i variabeln tal. Därför måste
scanf få veta var lagringsutrymmet finns.
Om vi hade utelämnat tecknet &,
och skrivit scanf("%d",tal), så hade tal
syftat på det värde som finns lagrat i variabeln.
Men scanf vill inte veta vad det gamla värdet (skatten
som ska ersättas) var,
utan bara var lagringsutrymmet (gömstället) finns.
Tecknet & anger att vi syftar på lagringsutrymmet,
inte på värdet.
Misströsta inte om stycket ovan förefaller obegripligt.
För tillfället räcker det att vi är medvetna om att
tecknet & behövs vid anrop av scanf.
Vad hade hänt om vi glömt ta med tecknet &
i programmet ovan? Jo, tyvärr hade C-kompilatorn accepterat
programmet utan någon som helst varning, och vid körningen
hade det gått så här:$ heltal
Ange ett tal: 34
Segmenteringsfel (core dumped)
$Programmet kraschar alltså efter att vi matat in det nya värdet.
På gott och ont får man göra hur man vill i C -
till och med vissa grova fel accepteras eftersom C-kompilatorer
utgår från att programmeraren alltid vet vad
hon/han gör. Därför är C oerhört flexibelt men samtidigt
oerhört farligt. Liksom en extremt vass kniv, är C ett
mycket användbart verktyg - men om man använder detta verktyg
oskickligt kan man göra sig ordentligt illa.
Ett bra sätt att minska risken för olyckor är att
ge gcc flaggan -Wall, vilken anger att vi vill
bli varnade för allt i programmet som ser mystiskt ut.
Om vi tar bort tecknet & från programmet ovan och kompilerar
det med flaggan -Wall, så går det så här:$ gcc -Wall heltal.c
heltal.c: In function `main':
heltal.c:8: warning: format argument is not a pointer (arg 2)
$Varningen avser att det andra argumentet i rad 8 verkar
skumt, det ''är inte en pekare''.
Nästa program ska läsa in två tal, beräkna deras summa och skriva ut resultatet. Så här kan det se ut:
#include <stdio.h>
int main(int argc,char *argv[])
{
int tal1,tal2,summa;
printf("Ange två tal: ");
scanf("%d%d",&tal1,&tal2);
summa=tal1+tal2;
printf("Summan av %d och %d är %d.\n",tal1,tal2,summa);
return 0;
}
Här deklareras tre heltalsvariabler,
nämligen tal1, tal2 och
summa.
Funktionen scanf läser in två heltal
och lagrar värdena i variablerna tal1
och tal2.
Sedan sätts värdet av variabeln summa
till summan av de båda talen,
och printf gör en utskrift.
I textsträngen som är det första argumentet till
funktionen printf har vi angett tre stycken
%d. För var och en av dessa %d måste
vi ange ytterligare ett argument till printf.
Det första %d byts vid utskriften ut mot det
argument som följer textsträngen, nämligen värdet av
variabeln tal1. Det andra %d byts ut
mot värdet av tal2, och det sista %d
byts ut mot värdet av summa.$ gcc -o heltal heltal.c
$ heltal
Ange två tal: 5 7
Summan av 5 och 7 är 12.
$
När en variabel för första gången tilldelas ett värde säger man att den initieras. C ger inget felmeddelande ifall en oinitierad variabel används, men vilket värde variabeln har då är oklart. Här är ett exempel, programmet oinitierad.c:
#include <stdio.h>
int main(int argc,char *argv[])
{
int tal;
printf("Talet har värdet %d.\n",tal);
return 0;
}
Jag hoppas att ingen tar efter programmet ovan. Det är
inte meningen att man ska använda en variabel
innan den initieras.$ gcc -o oinitierad oinitierad.c
$ oinitierad
Talet har värdet 0.
$Ovan hade variabeln tal värdet 0, men detta
är inget man kan lita på att den alltid har.
Istället kan man initiera variabeln vid deklarationen:
#include <stdio.h>
int main(int argc,char *argv[])
{
int tal=13;
printf("Talet har värdet %d.\n",tal);
return 0;
}
Om vi kompilerar och kör detta program, så ger det utskriften
Talet har värdet 13.