=========== C - Programmering Amiga OS 2.xx ==================== Av Kjell Cederfeldt. Del 5. Söndag den 19 April 1992. -------------------------------- Först en viktig miss! --------------------- Jag har glömt att tala om att funktioner, nyckelord och varablar mm 'case sensitivity', vilket betyder känslig för stora och små bokstäver. Man kan alltså inte skriva Printf() eller printF() när man menar printf(). Man kan inte heller skriva Int nisse; Man KAN skriva 'int Nisse;' men då är det Nisse som gäller hela tiden. Man kan om man så önskar deklara både nisse och Nisse. Detta är då två olika variblar. Det kommer i så fall att bli svårt att skilja dem åt. Så tänkt på att inte blanda stora och små bokstäver huller om buller. Detta kommmer inte att fungera. Fler datatyper! --------------- Vi har tidigare använt oss av datatypen int. Det är inte speciellt användbart att bara ha heltal i ett program. Därför finns det flera andra datatyper som vi skall titta närmare på nu. Varje datatyp motsvarar också datalängd. Datatypens läng mäts vanligast i bitar. Vad är då en bit? ----------------- En bit är det minsta värde som kan presenteras. En bit kan antingen vara 0 eller 1. Ett binärt talsystem är alltså uppbyggt på talbasen 2. När vi skriver tal i vår vanliga varadag. Så är talen uppbyggad på talbasen 10. Med andra ord är talet baserat på värdet tio. Varför det är så kan bero på att vi har tio fingrar. Du kanske inte har tänkt på det, med vi har "bara" tio siffror. Den första siffran är 0 och den sista siffran är ju 9. Man kan därför grovt sätt påstå att vi därför inte kan skriva ett större tal än 9. Men vi har därför utvecklat en teknik för detta. Efter 9 nollar vi och sätter en etta framför. Talet ser ut som 10. Ungefär som 0 och ett i minnet. Hände du med? Ettan framför nollan i talet 10 anger tiotals delen i talet 10 nollan anger entalsdelen. När vi kommer till talet 19 kan vi inte öka talet mer, eftersom det inte finn någon högre siffra än 9. Vi måste därför nolla entalsdelen och höja tiotalsdelen. Talet blir 20. Talet 4761 betstår av tusentalsdelen 4, hudratals- delen 7, tiotalsdelen 6 samt entalsdelen 1. Detta räknesätt heter decimalt talsystem. (Det är ju det vi använder hela dagarna). Datorn har bara 2 "fingrar" vilket motsvaras av ström på eller av i en logisk krets. Därför utvecklades ett nytt talsystem byggt på talbasen 2. Detta kallas för det binära talsystemt. Det fungerar faktiskt på samma sätt, med vi har bara två siffror, 0 och 1. Efter noll kommer ett. Och eftersom vi inte kan skriva ett större tal än 1 så måste vi nolla och sätta en etta framför. Känner du igen tekninken? Om vi skall skriva talet 3 så måste det alltså se ut som 11. Detta betyder binärt sätt tre och inte elva. 00 = 0 Båda bitarna är noll. 01 = 1 Den högsta siffran som kan finns innan "nollning" 10 = 2 Noll och ett i minnet. 11 = 3 Hur blir det efter 11 ? ___________ Här kommer en liten tabell. bit#: 7 ! 6 ! 5 ! 4 ! 3 ! 2 ! 1 ! 0 -----+----+----+----+---+---+---+--- Bivärde: 128 ! 64 ! 32 ! 16 ! 8 ! 4 ! 2 ! 1 Varje bit är som du ser dubbelt så mycket värd som den till höger. Det binära talet 1101 Ser alltså ut i tabellen enligt: bit#: 7 ! 6 ! 5 ! 4 ! 3 ! 2 ! 1 ! 0 -----+----+----+----+---+---+---+--- Bivärde: 128 ! 64 ! 32 ! 16 ! 8 ! 4 ! 2 ! 1 0 0 0 0 1 1 0 1 Vi kan då lägga ihop alla bitvärden som har en etta under sig. 1 + 4 + 8 = 13. Talet 1101 binärt är alltså 13 decimalt. Vi kan se det mer matematiskt 1 * 2³ + 1 * 2² + 0 * 2¹ + 1 * 2 (upph|jt). Vilket blir 13. En serie av 8 bitar kallas för en byte. Vi talar ofta om hur många byte vår dator har. 512 kb byte betyder alltså 512 kilo byte. (512 tusen byte). Två sammansatta byte kallas för ett word. Två sammansatta word (fyra bytes) kallas för ett longword. Detta är ord som vi kommer att anväda då vi programmer. (Speciellt Amigan). En byte är alltså 8 bitar Ett word är 16 bitar. Ett longword är 32 bitar. Vad blir 16 bitstalet 0110100101100100 ? Svar: _________________ Vilka datatyper finns? ---------------------- int - heltal long - heltal short - heltal unsigned - teckenlöst heltal float - flyttal (decimalpunktstal ex: 3.7) double - flyttal char - tecken (bokstäver siffror och likn.) Hur stor en datatyp är är mycket svårt att säga. Det varierar på dator till dator och från kompilator till kompilator. Man kan inte heller säga vad som är normalt. Med så här är det på Lattice 'C' (Om inget har ställts om). int = 32 bitar long = 32 bitar short = 16 bitar float = 32 bitar double = 64 bitar Enligt Ansi-C är reglerna. int - minst 16 bitar. long - minst 32 bitar dock inte mindre än int. short - minsta möjliga dock ej större än int. float - ? (vet ej men, troligen minst 32 bitar). double - minst lika stor som float dock ej mindre. unsigned används tillsammans med någon av de andra heltals datatyperna ex: unsigned short. Vilket betyder att alla tal blir possitiva. Vi skall göra ett lite program för att se storleken på de olika datatyperna. #include main() { int talint = 0; short talshort = 0; long tallong = 0; printf("Int : %d\n", sizeof(talint)); printf("Short: %d\n", sizeof(talshort)); printf("Long : %d\n", sizeof(tallong)); } Spara, Kompilera och länka. Kör nu programmet. På Amiga Lattice-C blev resultatet: Int : 4 Short: 2 Long : 4 Hmm? 4, 2 och 4. Jo datatypen int är 4, vilket motsvaras av fyra byte stort tal. Alltså ett longword, eller 32 bitar. Short är 2 byte stor, ett word, eller 16 bitar. Long är 4 byte stort, ett longword, eller 32 bitar. Programmet innehåller en ny funktion. sizeof() tar fram storleken av det som lämnas som argument. Som du ser lade vi ocskå in funktionsanroppet sizeof inne i printf-funkionen. Innan printf kan "köras" måste först funktionen sizeof "köras". Det största tal som en short kan visa skulle vara 65535, (om short är 16 bitar), men det stämmer inte helt och hållet. Short är ett heltal som skall kunna beräkna possitiva tal så väl som negativa tal. Talet för en short är mellan -32768 och 32767 (om short är 16 bitar). För en unsigned short talområdet mellan 0 till 65535 (om short är 16 bitar). Unsigned betyder att talet skall vara teckenlöst. Vad är det högsta tal som kan pressentras för: long? Svar:___________________ unsgined long? Svar:___________________ Om man vill snygga till det kan man skriva: #include main() { printf("Int : %d\n", sizeof(int)); printf("Short: %d\n", sizeof(short)); printf("Long : %d\n", sizeof(long)); } Vi behöver inte några variabler för att testa typ storleken. Deklarering av heltalstyper. --------------------------- Varje datatyp anges med ex: int, short long osv.. Detta görs vid deklarationsskedet med en en deklarationssats. De 7 grundläggande datatyper som finns i standard C är int, long, short, unsigned, char, float, double. Deklareringen ser ut enligt följande: int nisse; short inkomst; long utgift; Type unsigned ------------- Unsigned är normalt inte en egen datatyp utan en 'modifierare' av de tre datatyperna int, short och long. Man anger alltså inte unsigned ensamm tillsamman med en variabel utan tillsammans med int, short eller long. unsigned int pelle; unsigned short nisse; unsigned long karusell = 44; Flyttalsberäkning. ------------------ Typerna float och double är flyttals typer. Med flyttal kan man använda tal som ex: 3.14, 9.65 osv. Detta ger möjlighet till beräkningar av tal som kräver mer nogramhet. #include /* Tag in standard in/out-header */ #include /* Tag med math-library */ main() /* flyt.c - ett flyttals exempel */ { /* Lägg på momsen på bananpriset */ float moms, kr, bananer; /* Deklarering av variablerna */ bananer = 24.50; /* bananerna kostar 24.50 utan moms */ moms = 0.25; /* momssats */ kr = bananer * moms; /* Hur mycket moms */ printf("Momsen på bananerna är %f kronor\n", kr); kr = kr + bananer; /* Lägg till bananpriset till momsen */ printf("Bananerna kostar %f kronor\n", kr); } Spara programmet. Kompilera och länka med LC -Lm flyt.c Som du ser har det tillkommit en include till. Den skall vara med då vi använder flyttal. Vi har också en ny parameter till LC. Efter det stora L:et har vi ett litet m. Den behövs också då vi har flyttalsberäkningar. M:et står för math.library. Math.library är nödvändig för att kunna klara flyttalsberäkningar. Vad innehåller programmet? -------------------------- #include Vi har tagit med en ny includefil. Math.h. Den används vid flyttals- beräkningar och innehåller uppgifter som kompilatorn behöver. float moms, kr, bananer; Vi deklarerar tre variabler moms, kr och bananer. Alla av datatypen float. (Flyttal). Eftersom alla har samma datatyp sätter vi dem i samma sats (på samma rad). Varje variabel skills åt med ett komma- tecken. Statsen avslutas som vanligt med ett semikolon. bananer = 24.50; moms = 0.25; Vi tildelar variablerna bananer och moms sina värden. Detta görs i två tilldelningssatser. Varje sats avslutas med ett semikolon. kr = bananer * moms; Variabeln kr tilldelas efter att bananer har multipiserats med moms. variabeln skall nu innehålla hur mycket som är moms som skall läggas på när bananerna kostar 24.50. printf("Momsen på bananerna är %f kronor\n", kr); Momsen skrivs ut. kr = kr + bananer; Vi lägger ihop momsen med bananpriset och tilldelar variabeln kr detta nya värde. Som du ser kan kr användas på båda sider om = tecknet. Detta beror på att datorn måste först räkna ihop kr och bananer innan kr kan tilldelas ett nytt värde. printf("Bananerna kostar %f kronor\n", kr); Vi skriver ut det totala bananpriset inkl. moms Resultatet blev --------------- Momsen på bananerna är 6.125000 kronor Bananerna kostar 30.625000 kronor Som du ser blev fördelningen på decimalerna inte vad vi hande tänkt oss. Som chef för företaget billiga bananer kan vi inte visa dessa priser. Vi behöver justera programmet lite. #include #include main() /* flyt.c - ett flyttals exempel */ { /* Lägg på momsen på bananpriset */ float moms = 0.25, kr = 0, bananer = 24.50; /* Deklarering av variablerna */ printf("Momsen på bananerna är %5.2f kronor\n", kr = bananer * moms); printf("Bananerna kostar %5.2f kronor\n", kr = kr + bananer); } Spara programmet. Kompilera och länka med LC -Lm flyt.c Vad hände? ---------- float moms = 0.25, kr = 0, bananer = 24.50; Vi passade på att "snygga" till programmet lite. Vi tilldelade variabeln dess värde redan vid deklarationen. Då slipper tilldela dem sedan. Det ser mycket trevligare ut om man kan tilldela en variabel ett värde redan vid deklareringsfasen. printf("Momsen på bananerna är %5.2f kronor\n", kr = bananer * moms); Vi utför beräkningen av bananer * moms och tilldelar variabeln kr resultatet inne i printf-funktionen. (Ganska trevligt, men kan om man överdriver bli ganska svårläst). '%5.2f' talar om att fält- längden är 5 tecken stor, och att talet skall pressentreas med 2 decimalers. OBS talets nogranhet är fortfarande den samma, vi har bara angett för printf hur vi vill få det pressenterat i denna printf. printf("Bananerna kostar %5.2f kronor\n", kr = kr + bananer); Även här utför vi beräkning inne i printf-funktionen. Och vi formaterar utskriften av flyttalet till fältlängden 5 med 2 decimaler. Resultatet blev --------------- Momsen på bananerna är 6.12 kronor Bananerna kostar 30.62 kronor Ser lite mer prisvärt ut! Till sist --------- Från och med nu kommer jag alltid att utgå från att datatyperna har denna talstorlek. Om din kompilator har något annat. Få du själv ta hänsysn till detta. (Dock kommer det inte spela någon större roll för de flesta testprogram nu i början).