6.1 Kompilering och lite grundläggande information



Relevanta dokument
Programmera i C Varför programmera i C när det finns språk som Simula och Pascal??

Övning från förra gången: readword

Introduktion C-programmering

TDIU01 - Programmering i C++, grundkurs

Repetition C-programmering

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

Dagens föreläsning. Repetition. Repetition - Programmering i C. Repetition - Vad C består av. Repetition Ett första C-program

Pekare och arrayer. Indexering och avreferering

Datatyper och kontrollstrukturer. Skansholm: Kapitel 2) De åtta primitiva typerna. Typ Innehåll Defaultvärde Storlek

Programmeringsteknik med C och Matlab

C++ - En introduktion

*Pekarvärden *Pekarvariabler & *

Föreläsning 6 pekare och pekare tillsammans med arrayer

Pascal. reserverade ord fördefinierade funktioner och procedurer egendefinierade funktioner, procedurer och objekt

Dagens föreläsning. Repetition. Repetition - Programmering i C. Repetition - Vad C består av. Repetition Ett första C-program

Johan Karlsson Datavetenskap för teknisk kemi, 10p, moment 1 Datavetenskap Umeå Universitet. Tentamen

Pascal... Pascal. Pascal... Pascal...

Programmering i C. Vad är C? Målsättning. Litteratur. Jämförelse med Java. Exempel : Ett program som skriver ut texten Hello, world

TDIU01 - Programmering i C++, grundkurs

Programmering, grundkurs, 8.0 hp HI1024, omtentamen, TEN1. Tisdagen den 7 juni 2011,

Programmering, grundkurs, 8.0 hp, Elektro, KTH, hösten Programmering: att instruera en maskin att utföra en uppgift, kräver olika språk:

En kort text om programmering i C.

Klassdeklaration. Metoddeklaration. Parameteröverföring

2 Pekare och dynamiska variabler.

Grundläggande C-programmering del 2 Pekare och Arrayer. Ulf Assarsson

Agenda. Arrayer deklaration, åtkomst Makron Flerdimensionella arrayer Initiering Strängar Funktioner och arrayer. Övningar nu och då

Programmering i C++ En manual för kursen Datavetenskaplig introduktionskurs 5p

Programmering i C, 7,5 hp

Programmering, grundkurs, 8.0 hp HI1024, HI1900 etc., Tentamen TEN1. Måndagen den 10 januari 2011,

Typkonvertering. Java versus C

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Felsökning. Datatyper. Referenstyper. Metoder / funktioner

Grundläggande C-programmering del 2 Pekare och Arrayer. Ulf Assarsson

C-programmering, föreläsning 1 Jesper Wilhelmsson

Idag. Javas datatyper, arrayer, referenssemantik. Arv, polymorfi, typregler, typkonvertering. Tänker inte säga nåt om det som är likadant som i C.

Objektorienterad Programmering (TDDC77)

(Man brukar säga att) Java är... Denna föreläsning. Kompilering av Java. Historik: Java. enkelt. baserat på C/C++ Allmänt om Java

TDIU01 - Programmering i C++, grundkurs

I Skapa Hej.java och skriv programmet. I Kompilera med javac Hej.java. I Rätta fel och repetera tills du lyckas kompilera ditt program

Skriv i mån av plats dina lösningar direkt i tentamen. Skriv ditt kodnummer längst upp på varje blad.

Programmering med Java. Grunderna. Programspråket Java. Programmering med Java. Källkodsexempel. Java API-exempel In- och utmatning.

F4. programmeringsteknik och Matlab

Objektorienterad programmering i Java I. Uppgifter: 2 Beräknad tid: 5-8 timmar (OBS! Endast ett labbtillfälle) Att läsa: kapitel 5 6

Övningsuppgifter kapitel 8

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Strukturdiagram. Styra. Algoritmer. Val

Lite om felhantering och Exceptions Mer om variabler och parametrar Fält (eng array) och klassen ArrayList.

TDDC76 - Programmering och Datastrukturer

Användarhandledning Version 1.2

Föreläsning 2 Programmeringsteknik och C DD1316. Mikael Djurfeldt

Ulf Assarsson. Grundläggande C-programmering del 2 Pekare och Arrayer. Läromoment:

C++ - En introduktion

Java, klasser, objekt (Skansholm: Kapitel 2)

Vem är vem på kursen. Objektorienterad programvaruutveckling GU (DIT011) Kursbok Cay Horstmann: Big Java 3rd edition.

Att använda pekare i. C-kod

Övningsuppgifter till föreläsning 2 Variabler och uttryck

Föreläsning 3-4 Innehåll. Diskutera. Metod. Programexempel med metod

Programmering för språkteknologer I, VT2012. Rum

Planering Programmering grundkurs HI1024 HT 2014

Beräkningsvetenskap föreläsning 2

Poster ( structar ) Postdeklarationer

Föreläsning 10. Pekare (Pointers)

Föreläsning 3-4 Innehåll

Objektorienterad Programmering (TDDC77)

TDDC76 - Programmering och Datastrukturer

#include <stdio.h> #include <string.h>

Planering Programmering grundkurs HI1024 HT data

1 Texthantering. 1.1 Typen char. Exempel, skriv ut alfabetet

C-programmering, föreläsning 2 Jesper Wilhelmsson

1 Funktioner och procedurell abstraktion

C++-programmets beståndsdelar

PROGRAMMERING 2 GRUNDLÄGGANDE SEMANTIK 4

Strängar. Strängar (forts.)

Lathund. Pacific C för MS-DOS

2.1 Variabler. 2.2 Regler för namngivning i C. Programmering, grundkurs, 8.0 hp, Elektro, KTH, hösten Föreläsning 2

Logik och kontrollstrukturer

Föreläsning 10 Datalogi 1 DA2001. Utskrift på skärmen. Syntax. print( Hej ) Hur är det? Hej. print( Hej,end= ) print( Hur är det? ) HejHur är det?

Tentamen *:58/ID100V Programmering i C Exempel 3

Föreläsning 2. Variabler, tilldelning och kodblock{} if-satsen Logiska operatorer Andra operatorer Att programmera

4 Sammansatta datatyper

Byggstenar. C++-programmets beståndsdelar. C++-programmets beståndsdelar. Grundläggande datatyper

Parameteröverföring. Exempel. Exempel. Metodkropp

C-programmering. Målsättning Introducera programmering i C för de som inte har någon erfarenhet av C eller C++. Litteratur

Visual Basic, en snabbgenomgång

Översikt över Visual Basic

Introduktion till Datalogi DD1339. Föreläsning 2 22 sept 2014

Att deklarera och att använda variabler. Föreläsning 10. Synlighetsregler (2) Synlighetsregler (1)

Objektorienterad programmering i Java

Grunderna i C++ T A. Skapad av Matz Johansson BergströmLIMY

Hej Då, Karel! Programmering. Vårt första Javaprogram. hh.se/db2004. Java. Grundtyper, variabler och arrayer

Variabler och konstanter

TDIU01 - Programmering i C++, grundkurs

Föreläsning 2 Programmeringsteknik och C DD1316

Föreläsning 6: Metoder och fält (arrays)

LÖSNINGSFÖRSLAG Programmeringsteknik För Ing. - Java, 5p

Imperativ programmering. Föreläsning 2

Föreläsning 2 Programmeringsteknik och C DD1316. Programmering. Programspråk

1 Datorn som miniräknare. 1.1 Räkneoperationer. 1.2 Variabler

Övning2. Variabler. Data typer

Uttryck och villkor. Föreläsning 2

Kapitel 6. Hakparenteser fšr att ange index MŒnga všrden av samma typ

DD1314 Programmeringsteknik

Transkript:

6 Förhoppningsvis ska de C-konstruktioner som gås igenom här tillsammans med de exempelprogram som ges här och i andra delar av lab-pm vara tillräckliga för att ni ska kunna klara av laborationerna. Syftet är inte på något sätt att ge en heltäckande beskrivning av C eller ens en systematisk introduktion till språket. Den version av C som beskrivs här är traditionell Kernighan & Ritchie C. Det finns också en ANSI-standard för C där man har snyggat upp språket en del och lagt till några nya konstruktioner, men i detta lab-pm används traditionell C. 6.1 Kompilering och lite grundläggande information Kompilatorn startas med kommandot cc. För att t.ex. kompilera programmet foo.c och skapa den exekverbara filen foo skriver man: cc -o foo foo.c Alla C-program måste innehålla en funktion main där exekveringen startar. Vidare måste man se till att inkludera inkluderingsfiler för de bibliotek som man använder sig av. Följande är ett komplett C-program som kan kompileras och köras: #include <stdio.h> main() printf("concurrent Programming is fun!\n"); Programmet skriver ut ett meddelande på skärmen följt av ett radslutstecken. Funktionen printf, som används för utskriften, definieras i biblioteket stdio varför motsvarande inkluderingsfil stdio.h måste inkluderas. Parenteserna och som avgänsar funktionens kropp motsvarar begin respektive end i många andra språk. Sådana block kan nästlas och innehålla lokala variabeldeklarationer. Observera dock att funktioner inte får deklareras lokalt, vilket leder till att C-program får en flat struktur. Ytterligare en sak som bör påpekas är att C skiljer mellan stora och små bokstäver i nyckelord och identifierare. 6.2 Grundläggande variabeldeklarationer och konstantdefinitioner Variabler kan deklareras antingen lokalt i block eller globalt på toppnivån. Deklarationer skrivs i C med typen först och de deklarerade objekten efteråt. En deklaration av två heltalsvariabler respektive en teckenvariabel ser alltså ut som följer: int i, j; char ch; Det går också att initialisera variabler i samband med deklarationen: int i = 10, j = 20; char ch = a ; - 1 -

I (traditionell) C finns inte någon möjlighet att deklarera konstanter. Istället använder man makron vilkas förekomster i programtexten vid kompilering textuellt kommer att bytas ut mot makrots värde av en preprocessor innan själva C-kompilatorn tar vid. Nedanstående visar typisk definition och användning. Notera att man brukar skriva makron med stora bokstäver: #define SIZE 10 #define SPECIALCHAR a : if (i < SIZE && ch == SPECIALCHAR)... 6.3 Pekare Pekare är mycket viktiga i C och betydligt flexiblare än i många andra språk. C-pekare är t.ex. inte begränsade till att enbart referera till dynamiskt allokerade objekt, utan det är lätt skapa en pekare till en godtycklig variabel eller del av strukturerad variabel. Vidare kan vissa aritmetiska operationer utföras på pekare i C; en vanlig konstruktion är t.ex. att stega igenom en vektor med hjälp av en pekare som successivt får peka ut elementen i stället för att använda en indexvariabel. Två pekarvariabler, ip och cp, som kan lagra en pekare till ett heltal respektive till ett tecken, deklareras så här: int *ip; char *cp; Notera att variablerna ännu är oinitialiserade (d.v.s. inte pekar någonstans) i likhet med andra variabler som inte explicit initialiseras. Det går också bra att blanda deklarationer av variabler av bastypen och pekarvariabler. Observera placeringen av * : int i, j, *ip; char ch, *cp; De viktigaste operatorerna som hör ihop med pekare är & och *. & används för att plocka fram adressen till en variabel, d.v.s. &i representerar en pekare till innehållet i variabeln i. * gör tvärt om och utnyttjas för att komma åt det som en pekare pekar på. Följande är t.ex. ett omständligt sätt att tilldela 3 till i, givet deklarationerna ovan: ip = &i; *ip = 2; *ip = *ip + 1; Idén med den bakvända typnotationen vid deklaration av pekarvariabler ska nu förhoppningsvis vara klar: När * appliceras på ip så fås int. Alltså måste ip vara en pekare till heltal. Man får så att säga arbeta sig inifrån och ut för att kunna sluta sig till vilken typ variabeln har. Deklarationer fungerar genomgående på detta sätt i C. Som framgått ur det föregående är pekare i C typade och man kan därför inte blanda pekare av olika typer hur som helst. Ovan representerar t.ex. &i en heltalspekare eftersom i är ett heltal, så om man försöker tilldela &i till cp kommer kompilatorn att varna eftersom cp är en teckenpekarvariabel. C-kompilatorn håller också ordning på storleken av de element som en pekare av viss typ pekar på. Detta används för att göra aritmetik på pekare på ett vettigt sätt. Med deklarationerna ovan gäller t.ex. att (ip + 3) betecknar en heltalspekare som refererar till ett heltal som ligger - 2 -

tre heltal bortom det heltal som ip refererar till. Sådan pekararitmetik används ofta för att stega igenom vektorer. Det speciella pekarvärdet NULL betecknar en pekare som inte pekar någonstans alls. NULL är tilldelningskompatibel med alla pekartyper. 6.4 Vektorer och strängar Deklarationer av vektorer av heltal respektive tecken ser ut så här: int a[10]; char b[80], c[80]; Identifieraren a är nu namnet på ett utrymme som kan lagra tio stycken heltal, men i de allra flesta fall behandlar C a som en pekare till första elementet i utrymmet ifråga. Elementen adresseras som a[0], a[1],..., a[9] (undre indexgränsen är alltid 0 i C). Men eftersom a är en pekare, så hade man lika gärna kunnat adressera elementet a[3] som *(a+3)i enlighet med vad som sagts om pekararitmetik ovan. På samma sätt är b en pekare till ett utrymme som rymmer 80 tecken, b[0], b[1],..., b[79]. Detta har också konsekvenser när man tilldelar en vektor till en annan. Följande försök att tilldela innehållet i den vektor som b refererar till den vektor som c refererar till är felaktigt: c = b; /* FEL */ Jämför med att försöka tilldela ett heltal till ett annat. Vill man kopiera innehållet i b till c måste detta göras elementvis. Däremot går det bra att tilldela t.ex. b till en pekarvariabel cp deklarerad enligt ovan, vilket innebär att b och cp kommer att referera till samma minnesutrymme: b[2] = z ; cp = b; /* cp now points to array b.*/ a[9] = cp[2]; /* a[9] now contains z. */ *(cp+3) = x ; /* b[3] now contains x. */ När man skickar vektorer som parametrar till funktioner är det följaktligen bara adressen till (första elementet i) vektorn som skickas. Effekten blir alltså att en vektor alltid skickas som referensparameter, även om C ser det som att det är en pekare till vektorn som skickas över som en värdeparameter. Strängar representeras i C som vektorer av tecken. Variabeln b ovan kan alltså ses som en strängvariabel. Strängar i C avslutas alltid av tecken nummer noll, varför b rymmer strängar med en effektiv längd av upp till 79 tecken eftersom sluttecknet också måste få plats. 6.5 Poster Poster i C fungerar ungefär som poster i Pascal. Till skillnad från fallet med vektorer ovan är alltså variabler av posttyp riktiga variabler som verkligen innehåller posten, och inte bara en referens. Följande definierar en posttyp book, två variabler av denna typ, b1 och b2, samt en pekarvariabel bp som kan peka på poster av typen book: struct book char title[50], author[50]; int pages, price; float weight; b1, b2, *bp; - 3 -

Eftersom b1 och b2 är riktiga variabler, så är tilldelningen b1 = b2 i detta fall helt legal och kommer att kopiera innehållet i b2 till b1. När poster skickas som parametrar till (och returneras som resultat från) funktioner sker också kopiering, d.v.s. de skickas som värdeparametrar. Fälten i posten adresseras med punktnotation, vilket illustreras i följande exempel: b1.pages = 345; b1.price = 255; printf("title: %s.\n", b1.title); printf("price: %d.\n", b1.price); I enlighet med vad som sagts om vektorer ovan är b1.title och b2.author fortfarande bara pekare till respektive fält. Exemplet nedan visar hur man skapar en pekare till posten b1 och tilldelar denna till bp, samt hur adressering görs: bp = &b1; b2.price = (*bp).price; (*bp).weight = 123.4; Eftersom pekare till poster är vanligt förekommande, så finns ett förkortat skrivsätt för att komma åt fält i poster via en pekare: bp->weight = 123.4; printf("%d\n", pb->pages); 6.6 Funktionsdefinitioner Funktioner är de enda programenheter som finns i C; egentliga procedurer saknas. Man kan dock alltid behandla en funktion som om den vore en procedur genom att helt enkelt låta bli att ta hand om returvärdet. Man kan också explicit deklarera att en funktion är tänkt att användas som en procedur genom att låta den ha typen void, se nedan. Följande är en definition av en heltalsfunktion med tre parametrar: int foo(a, b, s) int a, b; char s[]; printf("%s\n", s); return 10 * a + b; Notera hur parametern s deklareras för att kunna ta emot en referens till en vektor. För funktionsargument är detta skrivsätt ekvivalent med att explicit deklarera parametern till att vara en pekare, d.v.s. i detta fall hade s lika gärna kunnat deklareras genom char *s. Funktion foo skulle kunna anropas enligt följande: x = foo(1, i, "Hej!"); där x och i är heltalsvariabler. I C, som vi redan har sett exempel på, skickas alla argument som värdeparametrar. Det är alltså värdet 1 och innehållet i i som skickas över och kopieras in i de formella parametrarna a och b. Strängar ses som teckenvektorer och representeras av en pekare till första tecknet. Det är denna pekare som kopieras in i s, i enlighet med hur C behandlar vektorer i allmänhet. - 4 -

Vill man inte returnera något värde från en funktion (d.v.s. om man vill ha en procedur) låter man funktionen ha typen void: void fie() /* Do something. */ Denna funktion tar alltså inga parametrar, returnerar inget resultat och anropas enligt: fie(); Observera att parenteserna måste vara med vid alla funktionsanrop, även om funktionen inte tar några parametrar! Det är ett mycket vanligt fel att glömma detta och kompilatorn kommer då inte att varna eller att ge något felmeddelande eftersom fie i sig själv är en pekare till funktionen, varför fie; är en laglig sats även om den inte utför något (ett godtyckligt uttryck blir en sats bara det följs av semikolon). Eftersom funktionsnamn ses som pekare till funktioner är det mycket enkelt att skicka funktioner som parametrar. Funktionen apply nedan tar en pekare till en heltalsfunktion som första argument och applicerar den utpekade funktionen på det andra argumentet. Notera likheten mellan hur funktionsparametern deklareras och dess användning: int foo(x) int x; return 2*x; int apply(f, x) int (*f)(), x; return (*f)(x); main() printf("%d\n", apply(foo, 10)); Slutligen ett exempel på hur man kan ordna så att man får utparametrar. Som tidigare nämnts passas ju alla parametrar som värdeparametrar i C, varför vi explicit måste skicka en pekare till den variabel i vilken vi vill ha resultatet, om vi vill ha en utparameter: void fum(p) int *p; *p = 10; fum anropas sedan enligt: fum(&i); där i är en heltalsvariabel. Detta är en mycket vanlig användning för operatorn &. Efter anropet har i värdet 10. - 5 -

6.7 Typkonverteringar Typkonverteringar används ganska flitigt i C, i synnerhet i samband med pekare. Typkonvertering indikeras genom att namnet på den typ som man vill konvertera ett uttryck till skrivs inom parentes framför uttrycket. Konvertering av heltal till ett dubbelprecisionsflyttal ser t.ex. ut så här (x antas vara av typen double): x = (double)(1+3); I många fall sker dessutom implicita typkonverteringar enligt ganska komplicerade regler. Funktionsargument av flyttalstyp konverteras t.ex. till dubbelprecisionsflyttal vid funktionsanrop. 6.8 Operatorer I denna sektion beskrivs några operatorer som kan vara bra att känna till. C är mycket rikt på operatorer varför endast de viktigaste tas med här. I C ser man tilldelning som en operator. Tilldelningsoperatorn skrivs = och värdet av ett tilldelningsuttryck är värdet på uttrycket till höger om likhetstecknet. Observera att likhetsoperatorn skrivs ==. Ett av de allra vanligaste misstagen när man börjar att programmera i C (om man t.ex. är van vid Pascal) är att man gör en tilldelning fast man tänkte testa likhet. Eftersom tilldelning är ett uttryck, kan man göra tilldelningar inne i andra uttryck för att få kompaktare källkod. Till exempel kan satserna: x = foo(7); if (x == 0) /* Do something */ kompaktare formuleras som: if ((x = foo(7)) == 0) /* Do something */ vilket är ett mycket vanligt sätt att uttrycka sig på i C. Nedan följer en lista över några C-operatorer i avtagande prioritetsording (varje rad motsvarar dock inte nödvändigtvis en egen prioritetsnivå). Några av dem har redan behandlats ovan. () []. -> Funktionsanrop, vektor- och postadressering. ++ -- Öka/minska variabel med 1, t.ex. i++ är detsamma som i=i+1;. & * - Unärt minus. Adressoperatorn och derefereringsoperatorn.! Logisk negation (true och false representeras av 1 respektive 0 i C, men godtyckligt tal skiljt från 0 ses som true av de logiska operatorerna). * / % Multiplikation, division och modulo. + - Addition och subtraktion. - 6 -

< <= >= > Relationsoperatorerna. ==!= Lika med respektive skiljt ifrån. && Logiskt OCH, kortsluten evaluering. Logiskt ELLER, kortsluten evaluering. = += Tilldelningsoperatorn och ökningsoperatorn. 6.9 Satser och styrstrukturer Nedan följer ett antal exempel på satser i C. Syntaxen ska förhoppningsvis klart framgå av dessa exempel. Det första exemplet är den sammansatta satsen: /* Satser */ Det går också bra att ha variabeldeklarationer i en sammansatt sats, som då kallas för block. Detta kan vara bekvämt om man behöver en temporär variabel endast lokalt i ett block. /* Variabeldeklarationer */ /* Satser */ Sammansatta satser och block kan nästlas efter behag. If-satsen och switch-satsen exemplifieras i det följande. Notera att både else-grenen och default-klausulen kan uteslutas: if (x == 5) /* Do something. */ else /* Do something else. */ switch (i) case 0: /* Do something. */ break;/* Must have break here or will fall through to next case. */ case 1: /* Do something else. */ break; case 5: case 6: case 7: /* Do something different if i = 5, 6, or 7. */ break; default: /* Do this if nothing else apply. */ break; Det följande är ett exempel på en while-loop: - 7 -

i = 0; while (i < 10) printf("i = %d\n", i); i++; Ovanstående är precis ekvivalent med följande for-loop: for (i = 0; i < 10; i++) printf("i = %d\n", i); Man kan även ha testvillkoret sist så att loopen alltid utförs minst en gång: do /* Do something. */ while (i <= 10); 6.10 In- och utmatning Vi har redan sett exempel på utmatning m.h.a. funktionen printf från biblioteket stdio ett antal gånger. Som första argument tar printf en formatsträng som innehåller den text som ska skrivas ut samt eventuellt ett antal omvandlingsspecifikationer som indikerar var i strängen och i vilket format resterande parametrar ska skrivas ut. Funktionen printf tar alltså ett variabelt antal argument och man måste själv se till att argumenten till typ och antal stämmer överens med vad som indikeras i formatsträngen. Annars så kan intressanta fenomen uppstå. Funktionen är mycket flexibel och ett otal olika effekter kan åstadkommas med olika typer av omvandlingsspecifikationer. De viktigaste är dock: %d Motsvarande argument är ett heltal. %c Argumentet är ett tecken. %f Argumentet är ett dubbelprecisionsflyttal. %s Argumentet är en sträng, d.v.s. pekare till en teckenvektor terminerad med tecknet \0. %% Skriv ut ett %-tecken. Ett exempel kan kanske vara klargörande: printf("integer %d, float %f, string %s.\n", 42, 3.14, "Hello"); När denna sats exekveras kommer följande att skrivas ut, följt av ett radslutstecken: Integer 42, float 3.140000, string Hello. Funktionen scanf från stdio.h kan användas för inläsning. Den påminner en del om printf och är i likhet med denna mycket flexibel. Två kompletta exempelprogram ges nedan för att illustrera hur scanf typiskt kan användas. Observera att förutom stdio.h så inkluderas filen stddef.h. Denna innehåller ett antal standarddefinitioner som ofta är bra att ha, t.ex. definitionen av NULL, men i programmen nedan hade den egentligen inte behövt inkluderas. - 8 -

Följande program läser ord separerade med en eller flera blanka och radframmatningar från standard input och skriver dem på standard output tills filslut signaleras (d.v.s. tills ctrl-d trycks först på en rad om inmatning sker från terminalen): #include <stddef.h> #include <stdio.h> main() char s[80]; while (scanf("%s", s)!= EOF) printf("word read: %s\n", s); /* Note: s is pointer to char array. */ Följande program läser heltal från standard input och skriver dem på standard output tills -1 har lästs. Notera hur en pekare till en heltalsvariabel skickas till scanf: #include <stddef.h> #include <stdio.h> main() int i; do scanf("%d", &i); /* Note: Must pass pointer to i, hence &i. */ printf("i = %d\n", i); while (i >= 0); - 9 -