Sei sulla pagina 1di 35

WELCOME to the WORLD of C

C is a programming language of many different dialects, similar to the way that each spoken language has many different dialects. In C, dialects don't exist because the speakers live in the North or South. Instead, they're there because there are many different compilers that support slightly different features. There are several common compilers:inparticular,BorlandC++,MicrosoftC++,andGNUC.Therearealsomanyfrontendenvironmentsforthe different compilersthe most common is DevC++ around GNU's G++ compiler. Some, such as GCC, are free, while othersarenot.Pleaseseethecompilerlistingformoreinformationonhowtogetacompilerandsetitup.Youshould notethatifyouareprogramminginConaC++compiler,thenyouwillwanttomakesurethatyourcompilerattempts tocompileCinsteadofC++toavoidsmallcompatibilityissues.

compiler will also have nonstandard functions (these functions are similar to slang spoken in different parts of a country).Sometimestheuseofnonstandardfunctionswillcauseproblemswhenyouattempttocompilesourcecode (theactualCcodewrittenbyaprogrammerandsavedasatextfile)withadifferentcompiler.ThesessionsuseANSI standard C and should not suffer from this problem; fortunately, since C has been around for quite a while, there shouldn'tbetoomanycompatibilityissuesexceptwhenyourcompilertriestocreateC++code.Ifyoudon'tyethave acompiler,Istronglyrecommendfindingonenow.Asimplecompilerissufficientforouruse,butmakesurethatyou

Every full C program begins inside a function called "main". A function is simply a collection of commands that do "something". The main function is always called when the program first executes. From main, we can call other functions, whether they be written by us or by others or use builtin language features. To access the standard functionsthatcomeswithyourcompiler,youneedtoincludeaheaderwiththe#includedirective.Whatthisdoesis effectivelytakeeverythingintheheaderandpasteitintoyourprogram.Let'slookataworkingprogram:

Ja y

Lets begin with First C Program

dogetoneinordertogetthemostfromthesesessions.

ob ot ix

Eachofthecompilersavailableisslightlydifferent.EachoneshouldsupporttheANSIstandardCfunctions,buteach

#include <stdio.h> int main() { printf( "I am alive! getchar(); return 0; } Beware.\n" );

Let's look at the elements of the program. The #include is a "preprocessor" directive that tells the compiler to put code from the header called stdio.h into our program before actually creating the executable. By including header files,youcangainaccesstomanydifferentfunctionsboththeprintfandgetcharfunctionsareincludedinstdio.h. ThesemicolonispartofthesyntaxofC.Ittellsthecompilerthatyou'reattheendofacommand.Youwillseelater that the semicolon is used to end most commands in C. The next important line is int main(). This line tells the compilerthatthereisafunctionnamedmain,andthatthefunctionreturnsaninteger,henceint.The"curlybraces"({ and})signalthebeginningandendoffunctionsandothercodeblocks.IfyouhaveprogrammedinPascal,youwill know them as BEGIN and END. Even if you haven't programmed in Pascal, this is a good way to think about their meaning.TheprintffunctionisthestandardCwayofdisplayingoutputonthescreen.Thequotestellthecompiler thatyouwanttooutputtheliteralstringasis(almost).The'\n'sequenceisactuallytreatedasasinglecharacterthat standsforanewline(we'lltalkaboutthislaterinmoredetail);forthetimebeing,justrememberthatthereareafew sequencesthat,whentheyappearinastringliteral,areactuallynotdisplayedliterallybyprintfandthat'\n'isoneof them.Theactualeffectof'\n'istomovethecursoronyourscreentothenextline.Again,noticethesemicolon:itis addedontotheendofalllines,suchasfunctioncalls,inC.Thenextcommandisgetchar().Thisisanotherfunction call:itreadsinasinglecharacterandwaitsfortheusertohitenterbeforereadingthecharacter.Thislineisincluded

beforeyoucanseetheoutput.Thiscommandkeepsthatwindowfromclosingbecausetheprogramisnotdoneyet becauseitwaitsforyoutohitenter.Includingthatlinegivesyoutimetoseetheprogramrun.Finally,attheendof theprogram,wereturnavaluefrommaintotheoperatingsystembyusingthereturnstatement.Thisreturnvalueis importantasitcanbeusedtotelltheoperatingsystemwhetherourprogramsucceededornot.Areturnvalueof0 meanssuccess.Thefinalbraceclosesoffthefunction.Youshouldtrycompilingthisprogramandrunningit.Youcan cutandpastethecodeintoafile,saveitasa.cfile,andthencompileit.Ifyouareusingacommandlinecompiler, such as Borland C++ 5.5, you should read the compiler instructions for information on how to compile. Otherwise 2

Ja y

becausemanycompilerenvironmentswillopenanewconsolewindow,runtheprogram,andthenclosethewindow

ob ot ix

compilingandrunningshouldbeassimpleasclickingabuttonwithyourmouse(perhapsthe"build"or"run"button). YoumightstartplayingaroundwiththeprintffunctionandgetusedtowritingsimpleCprograms.

Explaining your Code


Commentsarecriticalforallbutthemosttrivialprogramsandthistutorialwilloftenusethemtoexplainsectionsof code.Whenyoutellthecompilerasectionoftextisacomment,itwillignoreitwhenrunningthecode,allowingyou touseanytextyouwanttodescribetherealcode.TocreateacommentinC,yousurroundthetextwith/*andthen */toblockoffeverythingbetweenasacomment.Certaincompilerenvironmentsortexteditorswillchangethecolor ofacommentedareatomakeiteasiertospot,butsomewillnot.Becertainnottoaccidentallycommentoutcode (that is, to tell the compiler part of your code is a comment) you need for the program. When you are learning to program,itisalsousefultocommentoutsectionsofcodeinordertoseehowtheoutputisaffected.

Using Variables
Sofaryoushouldbeabletowriteasimpleprogramtodisplayinformationtypedinbyyou,theprogrammerandto describeyourprogramwithcomments.That'sgreat,butwhataboutinteractingwithyouruser?Fortunately,itisalso possibleforyourprogramtoacceptinput.Butfirst,beforeyoutrytoreceiveinput,youmusthaveaplacetostore thatinput.Inprogramming,inputanddataarestoredinvariables.Thereareseveraldifferenttypesofvariables;when youtellthecompileryouaredeclaringavariable,youmustincludethedatatypealongwiththenameofthevariable. Severalbasictypesincludechar,int,andfloat.Eachtypecanstoredifferenttypesofdata.Avariableoftypechar storesasinglecharacter,variablesoftypeintstoreintegers(numberswithoutdecimalplaces),andvariablesoftype floatstorenumberswithdecimalplaces.Eachofthesevariabletypeschar,int,andfloatiseachakeywordthatyou usewhenyoudeclareavariable.Somevariablesalsousemoreofthecomputer'smemorytostoretheirvalues.Itmay

rightvariablesizecanbeimportantformakingyourprogramefficientbecausesomevariablesrequiremorememory thanothers.Fornow,sufficeittosaythatthedifferentvariabletypeswillalmostallbeused!Beforeyoucanusea variable,youmusttellthecompileraboutitbydeclaringitandtellingthecompileraboutwhatits"type"is.Todeclare avariableyouusethesyntax<variabletype><nameofvariable>;.(Thebracketshereindicatethatyourreplacethe expressionwithtextdescribedwithinthebrackets.)Forinstance,abasicvariabledeclarationmightlooklikethis:


int myVariable;

Ja y

seem strange to have multiple variable types when it seems like some variable types are redundant. But using the

ob ot ix

Noteonceagaintheuseofasemicolonattheendoftheline.Eventhoughwe'renotcallingafunction,asemicolonis stillrequiredattheendofthe"expression".ThiscodewouldcreateavariablecalledmyVariable;nowwearefreeto usemyVariablelaterintheprogram.Itispermissibletodeclaremultiplevariablesofthesametypeonthesameline; eachoneshouldbeseparatedbyacomma.Ifyouattempttouseanundefinedvariable,yourprogramwillnotrun, and you will receive an error message informing you that you have made a mistake. Here are some variable declarationexamples:
int x; int a, b, c, d; char letter; float the_float;

While you can have multiple variables of the same type, you cannot have multiple variables with the same name. Moreover, you cannot have variables and functions with the same name. A final restriction on variables is that

segmentofcodesurroundedby{and}).SoinCyoumustdeclareallofyourvariablesbeforeyoudoanythingelse: Wrong
#include <stdio.h> int main() { /* wrong!

The variable declaration must appear first */

printf( "Declare x next" ); int x;

return 0; }

Fixed
int main() { int x;

#include <stdio.h>

printf( "Declare x first" );

Ja y

ob ot ix

variable declarations must come before other types of statements in the given "code block" (a code block is just a

return 0; }

Reading input
UsingvariablesinCforinputoroutputcanbeabitofahassleatfirst,butbearwithitanditwillmakesense.We'llbe usingthescanffunctiontoreadinavalueandthenprintftoreaditbackout.Let'slookattheprogramandthenpick apartexactlywhat'sgoingon.Youcanevencompilethisandrunitifithelpsyoufollowalong.
#include <stdio.h> int main() { int this_is_a_number;

scanf( "%d", &this_is_a_number );

printf( "You entered %d", this_is_a_number ); getchar(); return 0; }

Sowhatdoesallofthismean?We'veseenthe#includeandmainfunctionbefore;mainmustappearineveryprogram

stdio.hstandsfor"input/output";stdjuststandsfor"standard.")Thekeywordintdeclaresthis_is_a_numbertobean integer.Thisiswherethingsstarttogetinteresting:thescanffunctionworksbytakingastringandsomevariables

this tells the scanf function to read in an integer. The second argument of scanf is the variable, sort of. We'll learn moreaboutwhatisgoingonlater,butthegistofitisthatscanfneedstoknowwherethevariableisstoredinorderto changeitsvalue.Using&infrontofavariableallowsyoutogetitslocationandgivethattoscanfinsteadofthevalue ofthevariable.Thinkofitlikegivingsomeonedirectionstothesodaaisleandlettingthemgogetacocacolainstead offetchingthecokeforthatperson.The&givesthescanffunctiondirectionstothevariable.When theprogram runs,eachcalltoscanfchecksitsowninputstringtoseewhatkindsofinputtoexpect,andthenstoresthevalueinput into the variable. The second printf statement also contains the same '%d'both scanf and printf use the same 5

Ja y

modifiedwith&.Thestringtellsscanfwhatvariablestolookfor:noticethatwehaveastringcontainingonly"%d"

youintendtorun,andthe#includegivesusaccesstoprintf(aswellasscanf).(Asyoumighthaveguessed,theioin

ob ot ix

printf( "Please enter a number: " );

format for indicating values embedded in strings. In this case, printf takes the first argument after the string, the variablethis_is_a_number,andtreatsitasthoughitwereofthetypespecifiedbythe"formatspecifier".Inthiscase, printftreatsthis_is_a_numberasanintegerbasedontheformatspecifier. Sowhatdoesitmeantotreatanumberasaninteger?Iftheuserattemptstotypeinadecimalnumber,itwillbe truncated(thatis,thedecimalcomponentofthenumberwillbeignored)whenstoredinthevariable.Trytypingina sequenceofcharactersoradecimalnumberwhenyouruntheexampleprogram;theresponsewillvaryfrominputto input, but in no case is it particularly pretty. Of course, no matter what type you use, variables are uninteresting withouttheabilitytomodifythem.Severaloperatorsusedwithvariablesincludethefollowing:*,,+,/,=,==,>,<. The*multiplies,the/divides,thesubtracts,andthe+adds.Itisofcourseimportanttorealizethattomodifythe valueofavariableinsidetheprogramitisratherimportanttousetheequalsign.Insomelanguages,theequalsign comparesthevalueoftheleftandrightvalues,butinC==isusedforthattask.Theequalsignisstillextremelyuseful. Itsetsthevalueofthevariableontheleftsideoftheequalssignequaltothevalueontherightsideoftheequals

assigntheresulttoavariableontheleftside. Hereareafewexamples:

a = 4 * 6; /* (Note use of comments and of semicolon) a is 24 */

a = a + 5; /* a equals the original value of a with five added to it */ a == 5 /* Does NOT assign five to a. Rather, it checks to see if a equals 5.*/

Theotherformofequal,==,isnotawaytoassignavaluetoavariable.Rather,itcheckstoseeifthevariablesare equal.ItisextremelyusefulinmanyareasofC;forexample,youwilloftenuse==insuchconstructionsasconditional

Forexample:
a < 5 a > 5

/* Checks to see if a is less than five */ /* Checks to see if a is greater than five */

a == 5 /* Checks to see if a equals five, for good measure */

Ja y

statementsandloops.Youcanprobablyguesshow<and>function.Theyaregreaterthanandlessthanoperators.

ob ot ix

sign.Theoperatorsthatperformmathematicalfunctionsshouldbeusedontherightsideofanequalsigninorderto

If statements
Theabilitytocontroltheflowofyourprogram,lettingitmakedecisionsonwhatcodetoexecute,isvaluabletothe programmer.Theifstatementallowsyoutocontrolifaprogramentersasectionofcodeornotbasedonwhethera given condition is true or false. One of the important functions of the if statement is that it allows the program to selectanactionbasedupontheuser'sinput.Forexample,byusinganifstatementtocheckauserenteredpassword, yourprogramcandecidewhetherauserisallowedaccesstotheprogram. Withoutaconditionalstatementsuchastheifstatement,programswouldrunalmosttheexactsamewayeverytime, always following the same sequence of function calls. If statements allow the flow of the program to be changed, whichleadstomoreinterestingcode.Beforediscussingtheactualstructureoftheifstatement,letusexaminethe meaningofTRUEandFALSEincomputerterminology.Atruestatementisonethatevaluatestoanonzeronumber.A

return1ifthecomparisonistrue,or0ifthecomparisonisfalse.Forexample,thecheck0==2evaluatesto0.The check2==2evaluatestoa1.Ifthisconfusesyou,trytouseaprintfstatementtooutputtheresultofthosevarious comparisons(forexampleprintf("%d",2==1);)

Whenprogramming,theaimoftheprogramwilloftenrequirethecheckingofonevaluestoredbyavariableagainst anothervaluetodeterminewhetheroneislarger,smaller,orequaltotheother.Thereareanumberofoperators

>greaterthan5>4isTRUE <lessthan4<5isTRUE

>=greaterthanorequal4>=4isTRUE <=lessthanorequal3<=4isTRUE ==equalto5==5isTRUE

!=notequalto5!=4isTRUE It is highly probable that you have seen these before, probably with slightly different symbols. They should not 7

Ja y

thatallowthesechecks.Herearetherelationaloperators,astheyareknown,alongwithexamples:

ob ot ix

false statement evaluates to zero. When you perform comparison with the relational operators, the operator will

presentanyhindrancetounderstanding.NowthatyouunderstandTRUEandFALSEwellasthecomparisonoperators, letuslookattheactualstructureofifstatements.Thestructureofanifstatementisasfollows: if(statementisTRUE) Executethislineofcode Hereisasimpleexamplethatshowsthesyntax: if(5<10) printf("Fiveisnowlessthanten,that'sabigsurprise"); Here,we'rejustevaluatingthestatement,"isfivelessthanten",toseeifitistrueornot;withanyluck,it'snot!Ifyou want,youcanwriteyourownfullprogramincludingstdio.handputthisinthemainfunctionandrunittotest.To havemorethanonestatementexecuteafteranifstatementthatevaluatestotrue,usebraces,likewedidwiththe

statements,thecodethatdependsontheifstatementiscalledthe"body"oftheifstatement. Forexample: if(TRUE){

/*betweenthebracesisthebodyoftheifstatement*/ Executeallstatementsinsidethebody }

Irecommendalwaysputtingbracesfollowingifstatements.Ifyoudothis,youneverhavetoremembertoputthemin whenyouwantmorethanonestatementtobeexecuted,andyoumakethebodyoftheifstatementmorevisually clear.

Else

Sometimeswhentheconditioninanifstatementevaluatestofalse,itwouldbenicetoexecutesomecodeinsteadof thecodeexecutedwhenthestatementevaluatestotrue.The"else"statementeffectivelysaysthatwhatevercode afterit(whetherasinglelineorcodebetweenbrackets)isexecutediftheifstatementisFALSE.Itcanlooklikethis: 8

Ja y

ob ot ix

body of the main function. Anything inside braces is called a compound statement, or a block. When using if

if(TRUE){ /*ExecutethesestatementsifTRUE*/ } else{ /*ExecutethesestatementsifFALSE*/


}

Else if
Anotheruseofelseiswhentherearemultipleconditionalstatementsthatmayallevaluatetotrue,yetyouwantonly oneifstatement'sbody toexecute.Youcanusean"elseif"statementfollowinganifstatementanditsbody;that way,ifthefirststatementistrue,the"elseif"willbeignored,butiftheifstatementisfalse,itwillthencheckthe conditionfortheelseifstatement.Iftheifstatementwastruetheelsestatementwillnotbechecked.Itispossibleto usenumerouselseifstatementstoensurethatonlyoneblockofcodeisexecuted.Let'slookatasimpleprogramfor youtotryoutonyourown. #include<stdio.h>

intmain()/*Mostimportantpartoftheprogram! */ {

intage;/*Needavariable...*/

printf("Pleaseenteryourage");/*Asksforage*/

scanf("%d",&age);/*Theinputisputinage*/

printf("Youareprettyyoung!\n");/*Justtoshowyouitworks...*/ }

elseif(age==100){/*Iuseelsejusttoshowanexample*/ printf("Youareold\n"); } else{ printf("Youarereallyold\n");/*Executedifnootherstatementis 9

Ja y

if(age<100){/*Iftheageislessthan100*/

ob ot ix

*/ } return0; }

Loops
Loopsareusedtorepeatablockofcode.Beingabletohaveyourprogramrepeatedlyexecuteablockofcodeisone of the most basic but useful tasks in programming many programs or websites that produce extremely complex output(suchasamessageboard)arereallyonlyexecutingasingletaskmanytimes.(Theymaybeexecutingasmall number of tasks, but in principle, to produce a list of messages only requires repeating the operation of reading in some data and displaying it.) Now, think about what this means: a loop lets you write a very simple statement to produceasignificantlygreaterresultsimplybyrepetition. Onecaveat:beforegoingfurther,youshouldunderstandtheconceptofC'strueandfalse,becauseitwillbenecessary when working with loops (the conditions are the same as with if statements). There are three types of loops: for, while,anddo..while.Eachofthemhastheirspecificuses.Theyarealloutlinedbelow.FORforloopsarethemost usefultype. Thesyntaxforaforloopis

for ( variable initialization; condition; variable update ) { Code to execute while the condition is true

The variable initialization allows you to either declare a variable and give it a value or give a value to an already

continue to repeat itself. The variable update section is the easiest way for a for loop to handle changing of the variable.Itispossibletodothingslikex++,x=x+10,orevenx=random(5),andifyoureallywantedto,youcould callotherfunctionsthatdonothingtothevariablebutstillhaveausefuleffectonthecode.Noticethatasemicolon separates each of these sections, that is important. Also note that every single one of the sections may be empty, thoughthesemicolonsstillhavetobethere.Iftheconditionisempty,itisevaluatedastrueandtheloopwillrepeat untilsomethingelsestopsit. 10

Ja y

existingvariable.Second,theconditiontellstheprogramthatwhiletheconditionalexpressionistruetheloopshould

ob ot ix

Example:
#include <stdio.h> int main() { int x; /* The loop goes while x < 10, and x increases by one every loop*/ for ( x = 0; x < 10; x++ ) { /* Keep in mind that the loop condition checks the conditional statement before it loops again. consequently, when x equals 10 the loop breaks. x is updated before the condition is checked. */ printf( "%d\n", x ); } getchar(); }

Thisprogramisaverysimpleexampleofaforloop.xissettozero,whilexislessthan10itcallsprintftodisplaythe valueofthevariablex,anditadds1toxuntiltheconditionismet.Keepinmindalsothatthevariableisincremented afterthecodeintheloopisrunforthefirsttime.WHILEWHILEloopsareverysimple.

Thebasicstructureiswhile(condition){Codetoexecutewhiletheconditionistrue}Thetruerepresentsaboolean expression which could be x == 1 or while ( x != 7 ) (x does not equal 7). It can be any combination of boolean statements that are legal. Even, (while x ==5 || v == 7) which says execute the code while x equals five or while v equals 7. Notice that a while loop is like a strippeddown version of a for loop it has no initialization or update section.However,anemptyconditionisnotlegalforawhileloopasitiswithaforloop.

Example:
int main() {

#include <stdio.h>

int x = 0;

while ( x < 10 ) { /* While x is less than 10 */ printf( "%d\n", x ); x++; /* Update x so the condition can be met eventually */

Ja y
/* Don't forget to declare variables */

ob ot ix

11


} getchar(); }

Thiswasanothersimpleexample,butitislongerthantheaboveFORloop.Theeasiestwaytothinkoftheloopisthat whenitreachesthebraceattheenditjumpsbackuptothebeginningoftheloop,whichcheckstheconditionagain anddecideswhethertorepeattheblockanothertime,orstopandmovetothenextstatementaftertheblock. DO..WHILEDO..WHILEloopsareusefulforthingsthatwanttoloopatleastonce.Thestructureis


do { } while ( condition );

Noticethattheconditionistestedattheendoftheblockinsteadofthebeginning,sotheblockwillbeexecutedat leastonce.Iftheconditionistrue,wejumpbacktothebeginningoftheblockandexecuteitagain.Ado..whileloopis

"Loopwhiletheconditionistrue,andexecutethisblockofcode",ado..whileloopsays"Executethisblockofcode, andthencontinuetoloopwhiletheconditionistrue". Example:


#include <stdio.h> int main() { int x; x = 0; do {

/* "Hello, world!" is printed at least one time even though the condition is false*/ printf( "%d\n", x ); } while ( x != 0 ); getchar(); }

Ja y

ob ot ix

almostthesameasawhileloopexceptthattheloopbodyisguaranteedtoexecuteatleastonce.Awhileloopsays

12

Keepinmindthatyoumustincludeatrailingsemicolonafterthewhileintheaboveexample.Acommonerroristo forgetthatado..whileloopmustbeterminatedwithasemicolon(theotherloopsshouldnotbeterminatedwitha semicolon,addingtotheconfusion).Noticethatthisloopwillexecuteonce,becauseitautomaticallyexecutesbefore checkingthecondition. BreakandContinue Two keywords that are very important to looping are break and continue. The break command will exit the most immediatelysurroundingloopregardlessofwhattheconditionsoftheloopare.Breakisusefulifwewanttoexita loop under special circumstances. For example, let's say the program we're working on is a twoperson checkers game.Thebasicstructureoftheprogrammightlooklikethis:
while (true) { take_turn(player1); take_turn(player2); }

Thiswillmakethegamealternatebetweenhavingplayer1andplayer2taketurns.Theonlyproblemwiththislogicis thatthere'snowaytoexitthegame;theloopwillrunforever!Let'strysomethinglikethisinstead:
while(true) {

if (someone_has_won() || someone_wants_to_quit() == TRUE) {break;} take_turn(player1);

if (someone_has_won() || someone_wants_to_quit() == TRUE) {break;}

take_turn(player2); }

Thiscodeaccomplisheswhatwewanttheprimaryloopofthegamewillcontinueundernormalcircumstances,but underaspecialcondition(winningorexiting)theflowwillstopandourprogramwilldosomethingelse.Continueis 13

Ja y

ob ot ix

anotherkeywordthatcontrolstheflowofloops.Ifyouareexecutingaloopandhitacontinuestatement,theloop will stop its current iteration, update itself (in the case of for loops) and begin to execute again from the top. Essentially,thecontinuestatementissaying"thisiterationoftheloopisdone,let'scontinuewiththeloopwithout executingwhatevercodecomesafterme."Let'ssaywe'reimplementingagameofMonopoly.Likeabove,wewantto usealooptocontrolwhoseturnitis,butcontrollingturnsisabitmorecomplicatedinMonopolythanincheckers. Thebasicstructureofourcodemightthenlooksomethinglikethis:
for (player = 1; someone_has_won == FALSE; player++) { if (player > total_number_of_players) {player = 1;} {continue;} take_turn(player); } if (is_bankrupt(player))

Functions

Now that you should have learned about variables, loops, and conditional statements it is time to learn about functions.Youshouldhaveanideaoftheirusesaswehavealreadyusedthemanddefinedoneintheguiseofmain. Getchar is another example of a function. In general, functions are blocks of code that perform a number of pre definedcommandstoaccomplishsomethingproductive.Youcaneitherusethebuiltinlibraryfunctionsoryoucan createyourownfunctions.

Functionsthataprogrammerwriteswillgenerallyrequireaprototype.Justlikeablueprint,theprototypegivesbasic structuralinformation:ittellsthecompilerwhatthefunctionwillreturn,whatthefunctionwillbecalled,aswellas whatargumentsthefunctioncanbepassed.WhenIsaythatthefunctionreturnsavalue,Imeanthatthefunctioncan beusedinthesamemannerasavariablewouldbe.Forexample,avariablecanbesetequaltoafunctionthatreturns avaluebetweenzeroandfour.Forexample:

#include<stdlib.h>/*Includerand()*/

inta=rand();/*randisastandardfunctionthatallcompilershave*/ Donotthinkthat'a'willchangeatrandom,itwillbesettothevaluereturnedwhenthefunctioniscalled,butitwill 14

Ja y

ob ot ix

notchangeagain.Thegeneralformatforaprototypeissimple: returntypefunction_name(arg_typearg1,...,arg_typeargN); arg_typejustmeansthetypeforeachargumentforinstance,anint,afloat,orachar.It'sexactlythesamethingas whatyouwouldputifyouweredeclaringavariable.Therecanbemorethanoneargumentpassedtoafunctionor noneatall(wheretheparenthesesareempty),anditdoesnothavetoreturnavalue.Functionsthatdonotreturn valueshaveareturntypeofvoid.Let'slookatafunctionprototype: intmult(intx,inty); This prototype specifies that the function mult will accept two arguments, both integers, and that it will return an integer.Donotforgetthetrailingsemicolon.Withoutit,thecompilerwillprobablythinkthatyouaretryingtowrite the actual definition of the function. When the programmer actually defines the function, it will begin with the

the function is to execute, just as you would write it for the main function. Any of the arguments passed to the functioncanbeusedasiftheyweredeclaredintheblock.Finally,enditallwithacherryandaclosingbrace.Okay, maybenotacherry. Let'slookatanexampleprogram: #include<stdio.h> intmult(intx,inty); intmain() { intx; inty;

printf("Pleaseinputtwonumberstobemultiplied:"); scanf("%d",&x);

scanf("%d",&y); printf("Theproductofyourtwonumbersis%d\n",mult(x,y)); 15

Ja y

ob ot ix

prototype,minusthesemicolon.Thenthereshouldalwaysbeablock(surroundedbycurlybraces)withthecodethat

getchar(); } intmult(intx,inty) { returnx*y; } Thisprogrambeginswiththeonlynecessaryincludefile.Nextistheprototypeofthefunction.Noticethatithasthe finalsemicolon!Themainfunctionreturnsaninteger,whichyoushouldalwayshavetoconformtothestandard.You should not have trouble understanding the input and output functions if you've followed the previous tutorials. Noticehowprintfactuallytakesthevalueofwhatappearstobethemultfunction.Whatisreallyhappeningisprintfis acceptingthevaluereturnedbymult,notmultitself.Theresultwouldbethesameasifwehadusethisprintinstead

printf("Theproductofyourtwonumbersis%d\n",x*y);

Themultifunctionisactuallydefinedbelowmain.Becauseitsprototypeisabovemain,thecompilerstillrecognizesit asbeingdeclared,andsothecompilerwillnotgiveanerroraboutmultbeingundeclared.Aslongastheprototypeis present,afunctioncanbeusedevenifthereisnodefinition.However,thecodecannotberunwithoutadefinition eventhoughitwillcompile.

Prototypesaredeclarationsofthefunction,buttheyareonlynecessarytoalertthecompilerabouttheexistenceofa functionifwedon'twanttogoaheadandfullydefinethefunction.Ifmultweredefinedbeforeitisused,wecoulddo awaywiththeprototypethedefinitionbasicallyactsasaprototypeaswell.Returnisthekeywordusedtoforcethe functiontoreturnavalue.Notethatitispossibletohaveafunctionthatreturnsnovalue.Ifafunctionreturnsvoid, thereturnstatementisvalid,butonlyifitdoesnothaveanexpression.Inotherwords,forafunctionthatreturns void,thestatement"return;"islegal,butusuallyredundant.(Itcanbeusedtoexitthefunctionbeforetheendofthe function.) The most important functional (pun semiintended) question is why do we need a function? Functions havemanyuses.Forexample,aprogrammermayhaveablockofcodethathehasrepeatedfortytimesthroughout theprogram.Afunctiontoexecutethatcodewouldsaveagreatdealofspace,anditwouldalsomaketheprogram 16

Ja y

ob ot ix

morereadable.Also,havingonlyonecopyofthecodemakesiteasiertomakechanges.Wouldyourathermakeforty littlechangesscatteredallthroughoutapotentiallylargeprogram,oronechangetothefunctionbody?SowouldI. Another reason for functions is to break down a complex program into logical parts. For example, take a menu program that runs complex code when a menu choice is selected. The program would probably best be served by makingfunctionsforeachoftheactualmenuchoices,andthenbreakingdownthecomplextasksintosmaller,more manageabletasks,whichcouldbeintheirownfunctions.Inthisway,aprogramcanbedesignedthatmakessense when read. And has a structure that is easier to understand quickly. The worst programs usually only have the requiredfunction,main,andfillitwithpagesofjumbledcode.

Switch case
Switch case statements are a substitute for long if statements that compare a variable to several "integral" values ("integral"valuesaresimplyvaluesthatcanbeexpressedasaninteger,suchasthevalueofachar).Thebasicformat

each of the cases, and when one value matches the value of the variable, the computer continues executing the programfromthatpoint. switch(<variable>){ casethisvalue:

Codetoexecuteif<variable>==thisvalue break; casethatvalue:

Codetoexecuteif<variable>==thatvalue break; ... default:

Codetoexecuteif<variable>doesnotequalthevaluefollowinganyofthecases break; } Theconditionofaswitchstatementisavalue.Thecasesaysthatifithasthevalueofwhateverisafterthatcasethen 17

Ja y

ob ot ix

forusingswitchcaseisoutlinedbelow.Thevalueofthevariablegivenintoswitchiscomparedtothevaluefollowing

dowhateverfollowsthecolon.Thebreakisusedtobreakoutofthecasestatements.Breakisakeywordthatbreaks out of the code block, usually surrounded by braces, which it is in. In this case, break prevents the program from fallingthroughandexecutingthecodeinalltheothercasestatements.Animportantthingtonoteabouttheswitch statementisthatthecasevaluesmayonlybeconstantintegralexpressions.Sadly,itisn'tlegaltousecaselikethis: inta=10; intb=10; intc=20; switch(a){ caseb: /*Code*/

casec: /*Code*/ break; default: /*Code*/ break; }

Thedefaultcaseisoptional,butitiswisetoincludeitasithandlesanyunexpectedcases.Itcanbeusefultoputsome kindofoutputtoalertyoutothecodeenteringthedefaultcaseifyoudon'texpectitto.Switchstatementsserveasa simplewaytowritelongifstatementswhentherequirementsaremet.Oftenitcanbeusedtoprocessinputfroma user.Belowisasampleprogram,inwhichnotalloftheproperfunctionsareactuallydeclared,butwhichshowshow onewoulduseswitchinaprogram.

#include<stdio.h> voidplaygame(); 18

Ja y

ob ot ix

break;

voidloadgame(); voidplaymultiplayer(); intmain() { intinput; printf("1.Playgame\n"); printf("2.Loadgame\n"); printf("3.Playmultiplayer\n"); printf("4.Exit\n"); printf("Selection:"); scanf("%d",&input); switch(input){ case1:/*Notethecolon,notasemicolon*/

break; case2: loadgame(); break; case3: playmultiplayer(); break; case4:

printf("Thanksforplaying!\n"); break;

default:

printf("Badinput,quitting!\n"); break; } getchar(); }

Ja y

ob ot ix
19

playgame();

Thisprogramwillcompile,butcannotberununtiltheundefinedfunctionsaregivenbodies,butitservesasamodel (albeitsimple)forprocessinginput.If youdonot understandthisthentry mentally puttinginifstatementsforthe case statements. Default simply skips out of the switch case construction and allows the program to terminate naturally.Ifyoudonotlikethat,thenyoucanmakealooparoundthewholethingtohaveitwaitforvalidinput.You couldeasilymakeafewsmallfunctionsifyouwishtotestthecode.

Arrays
Arraysareusefulcrittersthatoftenshowupwhenitwouldbeconvenienttohaveonenameforagroupofvariables ofthesametypethatcanbeaccessedbyanumericalindex.Forexample,atictactoeboardcanbeheldinanarray andeachelementofthetictactoeboardcaneasilybeaccessedbyitsposition(theupperleftmightbeposition0and thelowerrightposition8).Atheart,arraysareessentiallyawaytostoremanyvaluesunderthesamename.Youcan makeanarrayoutofanydatatypeincludingstructuresandclasses.Onewaytovisualizeanarrayislikethis: [][][][][][]

Each of the bracket pairs is a slot in the array, and you can store information in slotthe information stored in the arrayiscalledanelementofthearray.Itisverymuchasthoughyouhaveagroupofvariableslinedupsidebyside. Let'slookatthesyntaxfordeclaringanarray.

intexamplearray[100];/*Thisdeclaresanarray*/

Thiswouldmakeanintegerarraywith100slots(theplacesinwhichvaluesofanarrayarestored).Toaccessaspecific

specificelementofthearray.Theonetrickisthatthefirstindexnumber,andthusthefirstelement,iszero,andthe lastisthenumberofelementsminusone.Theindicesfora100elementarrayrangefrom0to99.Becarefulnotto "walkofftheend"ofthearraybytryingtoaccesselement100!Whatcanyoudowiththissimpleknowledge?Lets sayyouwanttostoreastring,becauseChasnobuiltindatatypeforstrings,youcanmakeanarrayofcharacters. Forexample: charastring[100]; 20

Ja y

partelementofthearray,youmerelyputthearraynameand,inbrackets,anindexnumber.Thiscorrespondstoa

ob ot ix

willallowyoutodeclareachararrayof100elements,orslots.Thenyoucanreceiveinputintoitfromtheuser,and whentheusertypesinastring,itwillgointhearray,thefirstcharacterofthestringwillbeatposition0,thesecond characteratposition1,andsoforth.Itisrelatvelyeasytoworkwithstringsinthiswaybecauseitallowssupportfor any size string you can imagine all stored in a single variable with each element in the string stored in an adjacent locationthinkabouthowharditwouldbetostorenearlyarbitrarysizedstringsusingsimplevariablesthatonlystore onevalue.Sincewecanwriteloopsthatincrementintegers,it'sveryeasytoscanthroughastring: charastring[10]; inti=0; /*Usingscanfisn'treallythebestwaytodothis;we'lltalkaboutthat inthenexttutorial,onstrings*/ scanf("%s",astring);

{ if(astring[i]=='a') { printf("Youenteredana!\n"); } }

theformatstringis'%s'insteadof'%d';thisjusttellsscanftoreadinastringinsteadofaninteger.Second,wedon't use the ampersand! It turns out that when we pass arrays into functions, the compiler automatically converts the arrayintoapointertothefirstelementofthearray.Inshort,thearraywithoutanybracketswillactlikeapointer.So wejustpassthearraydirectlyintoscanfwithoutusingtheampersandanditworksperfectly. Also,noticethatto accesstheelementofthearray,wejustusethebracketsandputintheindexwhosevalueinterestsus;inthiscase, wegofrom0to9,checkingeachelementtoseeifit'sequaltothecharactera.Notethatsomeofthesevaluesmay actuallybeuninitializedsincetheusermightnotinputastringthatfillsthewholearraywe'lllookintohowstringsare handledinmoredetailinthenexttutorial;fornow,thekeyissimplytounderstandthepowerofaccessingthearray using a numerical index. Imagine how you would write that if you didn't have access to arrays! Oh boy. 21

Ja y

Let'slookatsomethingnewhere:thescanffunctioncallisataddifferentfromwhatwe'veseenbefore.Firstofall,

ob ot ix

for(i=0;i<10;++i)

Multidimensional arrays are arrays that have more than one index: instead of being just a single line of slots, multidimensional arrays can be thought of as having values that spread across two or more dimensions. Here's an easywaytovisualizeatwodimensionalarray: [][][][][] [][][][][] [][][][][] [][][][][] [][][][][] The syntax used to actually declare a two dimensional array is almost the same as that used for declaring a one dimensionalarray,exceptthatyouincludeasetofbracketsforeachdimension,andincludethesizeofthedimension. Forexample,hereisanarraythatislargeenoughtoholdastandardcheckersboard,with8rowsand8columns:

Youcaneasilyusethistostoreinformationaboutsomekindofgameortowritesomethingliketictactoe.Toaccess it,allyouneedaretwovariables,onethatgoesinthefirstslotandonethatgoesinthesecondslot.Youcanmake three dimensional, four dimensional, or even higher dimensional arrays, though past three dimensions, it becomes quitehardtovisualize.

Settingthevalueofanarrayelementisaseasyasaccessingtheelementandperforminganassignment.Forinstance,

<arrayname>[<arrayindexnumber>]=<value> forinstance,

/*setthefirstelementofmy_firsttobetheletterc*/ my_string[0]='c';

or,fortwodimensionalarrays

<arrayname>[<arrayindexnumber1>][<arrayindexnumber2>]=<whatever>; 22

Ja y

ob ot ix

inttwo_dimensional_array[8][8];

Letusnoteagainthatyoushouldneverattempttowritedatapastthelastelementofthearray,suchaswhenyou havea10elementarray,andyoutrytowritetothe[10]element.Thememoryforthearraythatwasallocatedforit willonlybetenlocationsinmemory,(theelements0through9)butthenextlocationcouldbeanything.Writingto random memory could cause unpredictable effectsfor example you might end up writing to the video buffer and changethevideodisplay,oryoumightwritetomemorybeingusedbyanopendocumentandalteringitscontents. Usually,theoperatingsystemwillnotallowthiskindofrecklessbehaviorandwillcrashtheprogramifittriestowrite tounallocatedmemory.Youwillfindlotsofusefulthingstodowitharrays,fromstoringinformationaboutcertain thingsunder onename,tomakinggamesliketictactoe.We'vealreadyseenoneexampleofusingloopstoaccess arrays;hereisanother,moreinteresting,example! #include<stdio.h> intmain() { intx;

intarray[8][8];/*Declaresanarraylikeachessboard*/ for(x=0;x<8;x++){ for(y=0;y<8;y++)

array[x][y]=x*y;/*Seteachelementtoavalue*/ } printf("ArrayIndices:\n"); for(x=0;x<8;x++){ for(y=0;y<8;y++) {

printf("[%d][%d]=%d",x,y,array[x][y]); }

printf("\n"); } getchar(); }

Ja y

ob ot ix
23

inty;

Justtotouchuponafinalpointmadebrieflyabove:arraysdon'trequireareferenceoperator(theampersand)when youwanttohaveapointertothem.Forexample: char*ptr; charstr[40]; ptr=str;/*Givesthememoryaddresswithoutareferenceoperator(&)*/ Asopposedto int*ptr; intnum; ptr=&num;/*Requires&togivethememoryaddresstotheptr*/

An introduction to pointers
Pointersareanextremelypowerfulprogrammingtool.Theycanmakesomethingsmucheasier,helpimproveyour program'sefficiency,andevenallowyoutohandleunlimitedamountsofdata.Forexample,usingpointersisoneway tohaveafunctionmodifyavariablepassedtoit.Itisalsopossibletousepointerstodynamicallyallocatememory, which means that you can write programs that can handle nearly unlimited amounts of data on the flyyou don't needtoknow,whenyouwritetheprogram,howmuchmemoryyouneed.Wow,that'skindofcool.Actually,it'svery cool,aswe'llseeinsomeofthenexttutorials.Fornow,let'sjustgetabasichandleonwhatpointersareandhowyou usethem.

Whatarepointers?Whyshouldyoucare?

alocalbank.Eachsafetydeposityboxwillhaveanumberassociatedwithitsothatyoucanquicklylookitup.These numbers are like the memory addresses of variables. A pointer in the world of safety deposit box would simply be anythingthatstoredthenumberofanothersafetydepositbox.Perhapsyouhavearichunclewhostoredvaluablesin hissafetydepositbox,butdecidedtoputthereallocationinanother,smaller,safetydepositboxthatonlystoreda cardwiththenumberofthelargeboxwiththerealjewelery.Thesafetydepositboxwiththecardwouldbestoring thelocationofanotherbox;itwouldbeequivalenttoapointer.Inthecomputer,pointersarejustvariablesthatstore memoryaddresses,usuallytheaddressesofothervariables. 24

Ja y

Pointersareaptlyname:they"point"tolocationsinmemory.Thinkofarowofsafetydepositboxesofvarioussizesat

ob ot ix

The cool thing is that once can talk about the address of a variable, you'll then be able to go to that address and retrievethedatastoredinit.Ifyouhappentohaveahugepieceofdatathatyouwanttopassintoafunction,it'salot easiertopassitslocationtothefunctionthattocopyeveryelementofthedata!Moreover,ifyouneedmorememory foryourprogram,youcanrequestmorememoryfromthesystemhowdoyouget"back"thatmemory?Thesystem tellsyouwhereitislocatedinmemory;thatistosay,yougetamemoryaddressback.Andyouneedpointerstostore the memory address. A note about terms: the word pointer can refer either to a memory address itself, or to a variablethatstoresamemoryaddress.Usually,thedistinctionisn'treallythatimportant:ifyoupassapointervariable into a function, you're passing the value stored in the pointerthe memory address. When I want to talk about a memoryaddress,I'llrefertoitasamemoryaddress;whenIwantavariablethatstoresamemoryaddress,I'llcallita pointer.Whenavariablestorestheaddressofanothervariable,I'llsaythatitis"pointingto"thatvariable. PointerSyntax Pointers require a bit of new syntax because when you have a pointer, you need the ability to both request the

special,youneedtotellthecompilerwhenyoudeclareyourpointervariablethatthevariableisapointer,andtellthe compilerwhattypeofmemoryitpointsto. Thepointerdeclarationlookslikethis: <variable_type>*<name>;

int*points_to_integer;

Noticetheuseofthe*.Thisisthekeytodeclaringapointer;ifyouadditdirectlybeforethevariablename,itwill declarethevariabletobeapointer.Minorgotcha:ifyoudeclaremultiplepointersonthesameline,youmustprecede eachofthemwithanasterisk:

/*onepointer,oneregularint*/ int*pointer1,nonpointer1; 25

Ja y

Forexample,youcoulddeclareapointerthatstorestheaddressofanintegerwiththefollowingsyntax:

ob ot ix

memory location it stores and the value stored at that memory location. Moreover, since pointers are somewhat

/*twopointers*/ int*pointer1,*pointer2; AsImentioned,therearetwowaystousethepointertoaccessinformation:itispossibletohaveitgivetheactual addresstoanothervariable.Todoso,simplyusethenameofthepointerwithoutthe*.However,toaccesstheactual memory location, use the *. The technical name for this doing this is dereferencing the pointer; in essence, you're takingthereferencetosomememoryaddressandfollowingit,toretrievetheactualvalue.Itcanbetrickytokeep trackofwhenyoushouldaddtheasterisk.Rememberthatthepointer'snaturaluseistostoreamemoryaddress;so whenyouusethepointer: call_to_function_expecting_memory_address(pointer);

theaddress.You'llprobablydothatanawfullot.Nevertheless,thepointeritselfissupposedtostoreanaddress,so whenyouusethebarepointer,yougetthataddressback.

PointingtoSomething:RetrievinganAddress

In order to have a pointer actually point to another variable it is necessary to have the memory address of that variablealso.Togetthememoryaddressofavariable(itslocationinmemory),putthe&signinfrontofthevariable

Conveniently,bothampersandandaddressofstartwitha;that'sausefulwaytorememberthatyouuse&togetthe addressofavariable.Forexample:

#include<stdio.h> intmain() {

intx;/*Anormalinteger*/

int*p;/*Apointertoaninteger("*p"isaninteger,sop mustbeapointertoaninteger)*/ 26

Ja y

name.Thismakesitgiveitsaddress.Thisiscalledtheaddressofoperator,becauseitreturnsthememoryaddress.

ob ot ix

thenitevaluatestotheaddress.Youhavetoaddsomethingextra,theasterisk,inordertoretrievethevaluestoredat

p=&x;/*Readit,"assigntheaddressofxtop"*/ scanf("%d",&x);/*Putavalueinx,wecouldalsousephere*/ printf("%d\n",*p);/*Notetheuseofthe*togetthevalue*/ getchar(); } Theprintfoutputsthevaluestoredinx.Whyisthat?Well,let'slookatthecode.Theintegeriscalledx.Apointerto anintegeristhendefinedasp.Thenitstoresthememorylocationofxinpointerbyusingtheaddressoperator(&)to gettheaddressofthevariable.Usingtheampersandisabitlikelookingatthelabelonthesafetydepositboxtosee itsnumberratherthanlookinginsidethebox,togetwhatitstores.Theusertheninputsanumberthatisstoredinthe variablex;remember,thisisthesamelocationthatispointedtobyp.Infact,sinceweuseanampersandtopassthe valuetoscanf,itshouldbeclearthatscanfisputtingthevalueintheaddresspointedtobyp.(Infact,scanfworks

looksattheaddressstoredinp,andgoestothataddressandreturnsthevalue.Thisisakintolookinginsideasafety depositboxonlytofindthenumberof(and,presumably,thekeyto)anotherbox,whichyouthenopen.Noticethat intheaboveexample,thepointerisinitializedtopointtoaspecificmemoryaddressbeforeitisused.Ifthiswasnot thecase,itcouldbepointingtoanything.Thiscanleadtoextremelyunpleasantconsequencestotheprogram.For instance,theoperatingsystemwillprobablypreventyoufromaccessingmemorythatitknowsyourprogramdoesn't own: this will cause your program to crash. If it let you use the memory, you could mess with the memory of any

Windowsandothermodernoperatingsystemswillstopyoufromaccessingthatmemoryandcauseyourprogramto crash.Toavoidcrashingyourprogram,youshouldalwaysinitializepointersbeforeyouusethem.Itisalsopossibleto initializepointersusingfreememory.Thisallowsdynamicallocationofmemory.Itisusefulforsettingupstructures suchaslinkedlistsordatatreeswhereyoudon'tknowexactlyhowmuchmemorywillbeneededatcompiletime,so youhavetogetmemoryduringtheprogram'sexecution.We'lllookatthesestructureslater,butfornow,we'llsimply examinehowtorequestmemoryfromandreturnmemorytotheoperatingsystem.Thefunctionmalloc,residingin thestdlib.hheaderfile,isusedtoinitializepointerswithmemoryfromfreestore(asectionofmemoryavailabletoall programs).mallocworksjustlikeanyotherfunctioncall.Theargumenttomallocistheamountofmemoryrequested (inbytes),andmallocgetsablockofmemoryofthatsizeandthenreturnsapointertotheblockofmemoryallocated. 27

Ja y

running programfor instance, if you had a document opened in Word, you could change the text! Fortunately,

ob ot ix

becuase of pointers!) The next line then passes *p into printf. *p performs the "dereferencing" operation on p; it

Sincedifferentvariabletypeshavedifferentmemoryrequirements,weneedtogetasizefortheamountofmemory mallocshouldreturn.Soweneedtoknowhowtogetthesizeofdifferentvariabletypes.Thiscanbedoneusingthe keywordsizeof,whichtakesanexpressionandreturnsitssize.Forexample,sizeof(int)wouldreturnthenumberof bytesrequiredtostoreaninteger. #include<stdlib.h> int*ptr=malloc(sizeof(int)); This code set ptr to point to a memory address of size int. The memory that is pointed to becomes unavailable to otherprograms.Thismeansthatthecarefulcodershouldfreethismemoryattheendofitsusagelestthememorybe losttotheoperatingsystemforthedurationoftheprogram(thisisoftencalledamemoryleakbecausetheprogram isnotkeepingtrackofallofitsmemory).Notethatitisslightlycleanertowritemallocstatementsbytakingthesize ofthevariablepointedtobyusingthepointerdirectly:

int*ptr=malloc(sizeof(*ptr));

What'sgoingonhere?sizeof(*ptr)willevaluatethesizeofwhateverwewouldgetbackfromdereferencingptr;since ptrisapointertoanint,*ptrwouldgiveusanint,sosizeof(*ptr)willreturnthesizeofaninteger.Sowhydothis? Well,ifwechangeptrtopointtosomethingelselikeafloat,thenwedon'thavetogobackandcorrectthemalloccall tousesizeof(float).Since ptrwouldbepointing to afloat,*ptrwouldbeafloat,sosizeof(*ptr)would stillgivethe

free(ptr);

Afterfreeingapointer,itisagoodideatoresetittopointto0.When0isassignedtoapointer,thepointerbecomes anullpointer,inotherwords,itpointstonothing.Bydoingthis,whenyoudosomethingfoolishwiththepointer(it happensalot,evenwithexperiencedprogrammers),youfindoutimmediatelyinsteadoflater,whenyouhavedone considerable damage. The concept of the null pointer is frequently used as a way of indicating a problemfor instance,mallocreturns0whenitcannotcorrectlyallocatememory.Youwanttobesuretohandlethiscorrectly sometimesyouroperatingsystemmightactuallyrunoutofmemoryandgiveyouthisvalue! 28

Ja y

rightsize!Thefreefunctionreturnsmemorytotheoperatingsystem.

ob ot ix

TakingStockofPointers PointersmayfeellikeaveryconfusingtopicatfirstbutIthinkanyonecancometoappreciateandunderstandthem.If you didn't feel like you absorbed everything about them, just take a few deep breaths and reread the lesson. You shouldn'tfeellikeyou'vefullygraspedeverynuanceofwhenandwhyyouneedtousepointers,thoughyoushould havesomeideaofsomeoftheirbasicuses.

Thinking about Bits


Thebyteisthelowestlevelatwhichwecanaccessdata;there'sno"bit"type,andwecan'taskforanindividualbit.In fact,wecan'tevenperformoperationsonasinglebiteverybitwiseoperatorwillbeappliedto,ataminimum,an entirebyteatatime.Thismeanswe'llbeconsideringthewholerepresentationofanumberwheneverwetalkabout applyingabitwiseoperator.(Notethatthisdoesn'tmeanwecan'teverchangeonlyonebitatatime;itjustmeanswe havetobesmartabouthowwedoit.)Understandingwhatitmeanstoapplyabitwiseoperatortoanentirestringof

numbersasstartingwiththemostsignificantbittotheleft(i.e.,10000000is128,and00000001is1).Regardlessof underlying representation, you may treat this as true. As a consequence, the results of the left and right shift operatorsarenotimplementationdependentforunsignednumbers(forsignednumbers,therightshiftoperatoris implementation defined). The leftshift operator is the equivalent of moving all the bits of a number a specified numberofplacestotheleft:
[variable]<<[number of places]

Forinstance,considerthenumber8writteninbinary00001000.Ifwewantedtoshiftittotheleft2places,we'dend upwith00100000;everythingismovedtothelefttwoplaces,andzerosareaddedaspadding.Thisisthenumber32

int mult_by_pow_2(int number, int power) {

return number<<power; }

Notethatinthisexample,we'reusingintegers,whichareeither2or4bytes,andthattheoperationgetsappliedto theentiresequenceof16or32bits.Butwhathappensifweshiftanumberlike128andwe'reonlystoringitina 29

Ja y

infact,leftshiftingistheequivalentofmultiplyingbyapoweroftwo.

ob ot ix

bits is probably easiest to see with the shifting operators. By convention, in C and C++ you can think about binary

singlebyte:10000000?Well,128*2=256,andwecan'tevenstoreanumberthatbiginabyte,soitshouldn'tbe surprisingthattheresultis00000000.Itshouldn'tsurpriseyouthatthere'sacorrespondingrightshiftoperator:>> (especially considering that I mentioned it earlier). Note that a bitwise rightshift will be the equivalent of integer division by 2. Why is it integer division? Consider the number 5, in binary, 00000101. 5/2 is 2.5, but if you are performing integer division, 5/2 is 2. When you perform a right shift by one: (unsigned int)5>>1, you end up with 00000010,astherightmost1getsshiftedofftheend;thisistherepresentationofthenumber2.Notethatthisonly holdstrueforunsignedintegers;otherwise,wearenotguaranteedthatthepaddingbitswillbeall0s. Generally, using the left and write shift operators will result in significantly faster code than calculating and then multiplying by a power of two. The shift operators will also be useful later when we look at how to manipulating individualbits.Fornow,let'slookatsomeoftheotherbinaryoperatorstoseewhattheycandoforus.

ThebitwiseANDoperatorisasingleampersand:&.AhandymneumonicisthatthesmallversionofthebooleanAND, &&, works on smaller pieces (bits instead of bytes, chars, integers, etc). In essence, a binary AND simply takes the logicalANDofthebitsineachpositionofanumberinbinaryform.Forinstance,workingwithabyte(thechartype):
01001000 & 10111000 = -------00001000

Themostsignificantbitofthefirstnumberis0,soweknowthemostsignificantbitoftheresultmustbe0;inthe secondmostsignificantbit,thebitofsecondnumberiszero,sowehavethesameresult.Theonlytimewhereboth

72 & 184 = 8

Bitwise OR

BitwiseORworksalmostexactly thesamewayasbitwiseAND.Theonlydifferenceisthatonlyoneofthetwobits needstobea1forthatposition'sbitintheresulttobe1.(Ifbothbitsarea1,theresultwillalsohavea1inthat position.)Thesybmolisapipe:|.Again,thisissimilartobooleanlogicaloperator,whichis||. 30

Ja y

bitsare1,whichistheonlytimetheresultwillbe1,isthefifthbitfromtheleft.Consequently,

ob ot ix

Bitwise AND


01001000 | 10111000 = -------11111000

andconsequently
72 | 184 = 248

Let'stakealookatanexampleofwhenyoucouldusejustthesefouroperatorstodosomethingpotentiallyuseful. Let'ssaythatyouwantedtokeeptrackofcertainbooleanattributesaboutsomethingforinstance,youmighthave eightcars(!)andwanttokeeptrackofwhichareinuse.Let'sassigneachofthecarsanumberfrom0to7. Sincewehaveeightitems,allwereallyneedisasinglebyte,andwe'lluseeachofitseightbitstoindicatewhetheror notacarisinuse.Todothis,we'lldeclareacharcalledin_use,andsetittozero.(We'llassumethatnoneofthecars areinitially"inuse".)


char in_use = 0;

onebitthatcorrespondstothatcar.Thestrategyissimple:usebitwiseoperatorstoensureeverybitoftheresultis zero except, possibly, for the bit we want to extract. Consider trying to extract the fifth bit from the right of a number:XX?XXXXXWewanttoknowwhatthequestionmarkis,andwearen'tconcernedabouttheXs.We'dliketo besurethattheXbitsdon'tinterferewithourresult,soweprobablyneedtouseabitwiseANDofsomekindtomake sure they are all zeros. What about the question mark? If it's a 1, and we take the bitwise AND of XX?XXXXX and 00100000,thentheresultwillbe00100000:
XX1XXXXX & 00100000 = -------00100000

Whereas,ifit'sazero,thentheresultwillbe00000000:
XX0XXXXX & 00100000 = -------00000000

Sowegetanonzeronumberif,andonlyif,thebitwe'reinterestedinisa1.Thisprocedureworksforfindingthebit inthenthposition.Theonlythinglefttodoistocreateanumberwithonlytheonebitinthecorrectpositionturned on.Thesearejustpowersoftwo,sooneapproachmightbetodosomethinglike: 31

Ja y

ob ot ix

Now,howcanwechecktomakesurethataparticularcarisfreebeforewetrytouseit?Well,weneedtoisolatethe


int is_in_use(int car_num) { // pow returns an int, but in_use will also be promoted to an int // so it doesn't have any effect; we can think of this as an operation // between chars return in_use & pow(2, car_num); }

Whilethisfunctionworks,itcanbeconfusing.Itobscuresthefactthatwhatwewanttodoisshiftabitoveracertain numberofplaces,sothatwehaveanumberlike00100000acoupleofzeros,aone,andsomemorezeros.(Theone could also be first or last 10000000 or 00000001.) We can use a bitwise leftshift to accomplish this, and it'll be muchfastertoboot.Ifwestartwiththenumber1,weareguaranteedtohaveonlyasinglebit,andweknowit'sto thefarright.We'llkeepinmindthatcar0willhaveitsdatastoredintherightmostbit,andcar7willbetheleftmost.
int is_in_use(int car_num) { return in_use & 1<<car_num; }

Notethatshiftingbyzeroplacesisalegaloperationwe'lljustgetbackthesamenumberwestartedwith.Allwe candoright nowischeckwhethera carisinuse; wecan'tactuallyset the inusebitforit. Therearetwocasesto consider: indicating a car is in use, and removing a car from use. In one case, we need to turn a bit on, and in the other,turnabitoff.Let'stackletheproblemofturningthebiton.Whatdoesthissuggestweshoulddo?Ifwehavea bit set to zero, the only way we know right now to set it to 1 is to do a bitwise OR. Conveniently, if we perform a bitwiseORwithonlyasinglebitsetto1(therestare0),thenwewon'taffecttherestofthenumberbecauseanything ORedwithzeroremainsthesame(1OR0is1,and0OR0is0).Againweneedtomoveasinglebitintothecorrect position:voidset_in_use(intcar_num){in_use=in_use|1<<car_num;}Whatdoesthisdo?Takethecaseofsetting therightmostbitto1:wehavesomenumber0XXXXXXX|10000000;theresult,1XXXXXXX.Theshiftisthesameas before;theonlydifferenceistheoperatorandthatwestoretheresult.Settingacartobenolongerinuseisabit morecomplicated.Forthat,we'llneedanotheroperator.

The Bitwise Complement


The bitwise complement operator, the tilde, ~, flips every bit. A useful way to remember this is that the tilde is 32

Ja y

ob ot ix

sometimescalledatwiddle,andthebitwisecomplementtwiddleseverybit:ifyouhavea1,it'sa0,andifyouhavea 0,it'sa1.Thisturnsouttobeagreatwayoffindingthelargestpossiblevalueforanunsignednumber:
unsigned int max = ~0;

0, of course, is all 0s: 00000000 00000000. Once we twiddle 0, we get all 1s: 11111111 11111111. Since max is an unsignedint,wedon'thavetoworryaboutsignbitsortwoscomplement.Weknowthatall1sisthelargestpossible number.Notethat~and!cannotbeusedinterchangeably.WhenyoutakethelogicalNOTofanonzeronumber, you get 0 (FALSE). However, when you twiddle a nonzero number, the only time you'll get 0 is when every bit is turnedon.(ThisnonequivalenceprincipleholdstrueforbitwiseANDtoo,unlessyouknowthatyouareusingstrictly the numbers 1 and 0. For bitwise OR, to be certain that it would be equivalent, you'd need to make sure that the underlyingrepresentationof0isallzerostouseitinterchangeably.Butdon'tdothat!It'llmakeyourcodeharderto understand.)

wanttoleaveotherbitsunaffected,butthatifwehavea1inthegivenposition,wewantittobea0.Takesometime tothinkabouthowtodothisbeforereadingfurther.Weneedtocomeupwithasequenceofoperationsthatleaves 1sand0sinthenontargetpositionunaffected;before,weusedabitwiseOR,butwecanalsouseabitwiseAND.1 AND1is1,and0AND1is0.Now,toturnoffabit,wejustneedtoANDitwith0:1AND0is0.Soifwewantto indicatethatcar2isnolongerinuse,wewanttotakethebitwiseANDofXXXXX1XXwith11111011.Howcanweget thatnumber?Thisiswheretheabilitytotakethecomplementofanumbercomesinhandy:wealreadyknowhowto

~(1<<position)

changeistheoneofthecar_numwe'reinterestedin.
int set_unused(int car_num) {

in_use = in_use & ~(1<<position); }

Youmightbethinkingtoyourself,butthisiskindofclunky.Weactuallyneedtoknowwhetheracarisinuseornot(if thebitisonoroff)beforewecanknowwhichfunctiontocall.Whilethisisn'tnecessarilyabadthing,itmeansthat 33

Ja y

Nowthatwehavethis,wecanjusttakethebitwiseANDofthiswiththecurrentfieldofcars,andtheonlybitwe'll

turnasinglebiton.Ifweturnonebitonandtakethecomplementofthenumber,wegeteverybitonexceptthatbit:

ob ot ix

Nowthatwehaveawayofflippingbits,wecanstartthinkingabouthowtoturnoffasinglebit.Weknowthatwe

we do need to know a little bit about what's going on. There is an easier way, but first we need the last bitwise operator:exclusiveor.

Bitwise Exclusive-Or (XOR)


Thereisnobooleanoperatorcounterparttobitwiseexclusiveor,butthereisasimpleexplanation.Theexclusiveor operationtakestwoinputsandreturnsa1ifeitheroneortheotheroftheinputsisa1,butnotifbothare.Thatis,if bothinputsare1orbothinputsare0,itreturns0.Bitwiseexclusiveor,withtheoperatorofacarrot,^,performsthe exclusiveoroperationoneachpairofbits.ExclusiveoriscommonlyabbreviatedXOR.Forinstance,ifyouhavetwo numbersrepresentedinbinaryas10101010and01110010thentakingthebitwiseXORresultsin11011000.It'seasier toseethisifthebitsarelinedupcorrectly:
01110010 ^ 10101010 --------

YoucanthinkofXORinthefollowingway:youhavesomebit,either1or0,thatwe'llcallA.WhenyoutakeAXOR0, thenyoualwaysgetAback:ifAis1,youget1,andifAis0,youget0.Ontheotherhand,whenyoutakeAXOR1,you flipA.IfAis0,youget1;ifAis1,youget0.SoyoucanthinkoftheXORoperationasasortofselectivetwiddle:if youapplyXORtotwonumbers,oneofwhichisall1s,yougettheequivalentofatwiddle.Additionally,ifyouapply theXORoperationtwicesayyouhaveabit,A,andanotherbitB,andyousetCequaltoAXORB,andthentakeC XORB:yougetAXORBXORB,whichessentiallyeitherflipseverybitofAtwice,orneverflipsthebit,soyoujustget

twointegervariableswithoutatemporaryvariable?(Onceyou'vefigureditout,checkthesolution.)Howdoesthat helpus?Well,rememberthefirstprinciple:XORingabitwith0resultsinthesamebit.Sowhatwe'dreallyliketobe abletodoisjustcallonefunctionthatflipsthebitofthecarwe'reinterestedinitdoesn'tmatterifit'sbeingturned onorturnedoffandleavestherestofthebitsunchanged.Thissoundsanawfullotlikethewhatwe'vedoneinthe past;infact,weonlyneedtomakeonechangetoourfunctiontoturnabiton.InsteadofusingabitwiseOR,weusea bitwiseXOR.Thisleaveseverythingunchanged,butflipsthebitinsteadofalwaysturningiton:


void flip_use_state(int car_num) { in_use = in_use ^ 1<<car_num; }

Ja y

backA.(YoucanalsothinkofBXORBascancellingout.)Asanexercise,canyouthinkofawaytousethistoexchange

ob ot ix

11011000

34

When should you use bitwise operators?


Bitwiseoperatorsaregoodforsavingspacebutmanytimes,spaceishardlyanissue.Andoneproblemwithworking attheleveloftheindividualbitsisthatifyoudecideyouneedmorespaceorwanttosavesometimeforinstance,if weneededtostoreinformationabout9carsinsteadof8thenyoumighthavetoredesignlargeportionsofyour program.Ontheotherhand,sometimesyoucanusebitwiseoperatorstocleverlyremovedependencies,suchasby using ~0 to find the largest possible integer. And bit shifting to multiply by two is a fairly common operation, so it doesn'taffectreadabilityinthewaythatadvanceduseofbitmanipulationcaninsomecases(forinstance,usingXOR toswitchthevaluesstoredintwovariables).Therearealsotimeswhenyouneedtousebitwiseoperators:ifyou're workingwithcompressionorsomeformsofencryption,orifyou'reworkingonasystemthatexpectsbitfieldstobe usedtostorebooleanattributes.

Summary
argument
bit_arg<<shift_arg

Shiftsbitstoofbit_argshift_argplacestotheleftequivalenttomulitplicationby2^shift_arg
bit_arg>>shift_arg

Shiftsbitstoofbit_argshift_argplacestotherightequivalenttointegerdivisionby2^shift_argWorksonthebits ofbotharguments
left_arg & right_arg

TakesthebitwiseANDofleft_argandright_arg
left_arg ^ right_arg

left_arg | right_arg

Worksonthebitsofonlyargument
~arg

Reverses the bits of arg Skills and knowledge You also know a couple of neat tricks that you can use when performanceiscritical,orspaceisslow,oryoujustneedtoisolateandmanipulateindividualbitsofanumber.And younowshouldhaveabettersenseofwhatgoesonatthelowestlevelsofyourcomputer. 35

Ja y

TakesthebitwiseXORofleft_argandright_arg

ob ot ix

Youshouldnowbefamiliarwithsixbitwiseoperators:Worksonbitsforleftargument,takesanintegerasasecond

Potrebbero piacerti anche