Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
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
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.
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
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!
return 0; }
Fixed
int main() { int x;
#include <stdio.h>
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;
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
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 = 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 */
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
Whenprogramming,theaimoftheprogramwilloftenrequirethecheckingofonevaluestoredbyavariableagainst anothervaluetodeterminewhetheroneislarger,smaller,orequaltotheother.Thereareanumberofoperators
>greaterthan5>4isTRUE <lessthan4<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
/*betweenthebracesisthebodyoftheifstatement*/ Executeallstatementsinsidethebody }
Else
Ja y
ob ot ix
body of the main function. Anything inside braces is called a compound statement, or a block. When using if
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...*/ }
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(); }
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(); }
Noticethattheconditionistestedattheendoftheblockinsteadofthebeginning,sotheblockwillbeexecutedat leastonce.Iftheconditionistrue,wejumpbacktothebeginningoftheblockandexecuteitagain.Ado..whileloopis
/* "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) {
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.
#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);
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:
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*/
#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*/
printf("Thanksforplaying!\n"); break;
default:
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
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;
printf("[%d][%d]=%d",x,y,array[x][y]); }
printf("\n"); } getchar(); }
Ja y
ob ot ix
23
inty;
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
int*points_to_integer;
/*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
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));
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.
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
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
Ja y
bitsare1,whichistheonlytimetheresultwillbe1,isthefifthbitfromtheleft.Consequently,
ob ot ix
Bitwise AND
01001000 | 10111000 = -------11111000
andconsequently
72 | 184 = 248
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
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.
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.)
~(1<<position)
changeistheoneofthecar_numwe'reinterestedin.
int set_unused(int car_num) {
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.
Ja y
backA.(YoucanalsothinkofBXORBascancellingout.)Asanexercise,canyouthinkofawaytousethistoexchange
ob ot ix
11011000
34
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