Obecný formulář
V programu se tělo funkce spouští voláním funkce a proces je podobný jako podprogramy v jiných jazycích.
VClanguage,obecná formafunkcecallis:
Název funkce (aktuální seznam parametrů)
Whencallingafunctionwithoutparameters,thereisnoactualparameterlist..Theparametersintheactualparametertablecanbeconstants,variables,orotherstructureddataandexpressions.Separateeachactualparameterwithacomma.
Uživatelský prostor (uživatelský režim) a prostor jádra (režim jádra)
Prostor procesů operačního systému lze rozdělit na uživatelský prostor a prostor jádra, které vyžadují různá spouštěcí oprávnění. Funkce se spouští v uživatelském prostoru.
Včetně obsahu
Výraz funkce
Funkce se objevují ve výrazech jako v jedné položce výrazů a při výpočtu výrazů se účastní hodnoty obratu.
Příkaz funkce
Obecná forma volání funkce plus středníka představuje příkaz funkce. Například: printf("%d",a);scanf("%d",&b);všechny funkce volání ve formě příkazů funkcí.
FunctionArguments
Thefunctionappearsastheactualparameterofanotherfunctioncall.Inthiscase,thereturnvalueofthefunctionistransmittedasanactualparameter,sothefunctionmusthaveareturnvalue.Forexample:printf("%d",max(x,y));Thatis,thereturnvalueofthemaxcallisusedastheactualparameteroftheprintffunction.Anotherissuethatshouldbepaidattentiontoinfunctioncallsistheorderofevaluation.Theso-calledevaluationorderreferstowhetherthequantitiesintheactualparametertableareusedfromlefttorightorfromrighttoleft.Inthisregard,theregulationsofeachsystemarenotnecessarilythesame.Ithasbeenmentionedintheintroductionoftheprintffunction,andIwillemphasizeitagainfromtheperspectiveoffunctioncalls.
[Příklad]
hlavní()
{inti=8;printf("%d\n%d\n%d\n%d\n",++i,--i,i++,i--);}
Pokud se vyhodnocuje zprava doleva. Průběžný výsledek by měl být:
8
7
7
8
Například v tiskovém prohlášení++i,--i,i++,i--vyhodnoťte zleva doprava, výsledek by měl být:
9
8
8
9
Itshouldbenotedthatwhetheritisevaluatedfromlefttorightorfromrighttoleft,theoutputorderisthesame,thatis,theoutputorderisalwaysTheorderoftheactualparametersisthesameasintheactualparameterlist.SinceTurboCiscurrentlyevaluatedfromrighttoleft,theresultis8,7,7,8.Ifyoustilldon’tunderstandtheabovequestions,youwillunderstandafteratryonthecomputer.
Declarationandfunctionprototypeofthecalledfunction
Beforecallingafunctioninthemaincallingfunction,thecalledfunctionshouldbeexplained(declared),whichisthesameasbeforeusingvariables.Thevariabledescriptionisthesame.Thepurposeofexplainingthecalledfunctioninthecallingfunctionistomakethecompilersystemknowthetypeofthereturnvalueofthecalledfunction,sothatthereturnvaluecanbeprocessedaccordinglyinthecallingfunctionaccordingtothistype.
Obecný tvar:
Specifikátor typu se nazývánázev funkce (parametr typu, parametr typu...);
Nebo:
Specifikátor typu se nazývánázev funkce (typ, typ...);
Thetypeandnameoftheformalparameteraregivenintheparentheses,oronlythetypeoftheformalparameterisgiven.Thisfacilitateserrordetectionbythecompilersystemtopreventpossibleerrors.
Například popis maximální funkce v hlavní funkci je:
intmax(inta,intb);
Orwrittenas:
intmax(int,int);
TheClanguagealsostipulatesthatthefunctiondescriptionofthecalledfunctioninthecallingfunctioncanbeomittedinthefollowingsituations.
1)Ifthereturnvalueofthecalledfunctionisanintegerorcharactertype,youcancallthecalledfunctiondirectlywithoutexplainingit.Atthistime,thesystemwillautomaticallytreatthereturnvalueofthecalledfunctionasaninteger.ThisisthecasewhenthefunctionsisnotdescribedinthemainfunctionofExample8.2anditiscalleddirectly.
2)Whenthefunctiondefinitionofthecalledfunctionappearsbeforethecallingfunction,thecallingfunctioncanalsobecalleddirectlywithoutfurtherexplainingthecalledfunction.Forexample,inExample8.1,thedefinitionofthefunctionmaxisplacedbeforethemainfunction,sothefunctiondescriptionofthemaxfunctioncanbeomittedinthemainfunctionintmax(inta,intb).
3)Ifthetypeofeachfunctionisspecifiedoutsidethefunctionbeforethedefinitionofallthefunctions,theninthesubsequentcallingfunctions,thecalledfunctioncannolongerbedescribed.Forexample:
charstr(inta);
floatf(floatb);
hlavní()
{……}
charstr(inta)
{……)
floatf(floatb)
{……}
Thefirstandsecondlineshavepre-explainedthestrfunctionandtheffunction.Therefore,thestrandffunctionscanbecalleddirectlyinthefollowingfunctionswithoutfurtherexplanation.
4)Thecallofthelibraryfunctiondoesnotneedtobeexplained,buttheheaderfileofthefunctionmustbeincludedinthefrontofthesourcefilewiththeincludecommand.
Nestedcall
NestedfunctiondefinitionsarenotallowedinClanguage.Therefore,thefunctionsareparallel,andthereisnoproblemoftheupperlevelfunctionandthenextlevelfunction.ButtheClanguageallowsacalltoanotherfunctiontoappearinthedefinitionofafunction.Inthisway,nestedcallsoffunctionsappear.Thatis,otherfunctionsarecalledinthecalledfunction.Thisissimilartothenestingofsubroutinesinotherlanguages.Therelationshipcanberepresentedasshowninthefigure.
Thefigureshowsatwo-levelnestingsituation.Theexecutionprocessis:whenthestatementthatcallsfunctionainthemainfunctionisexecuted,functionaisswitchedto,whenfunctionbiscalledinfunctiona,functionbisswitchedtoexecution,andfunctionbisexecutedtoreturntothebreakpointoffunctionatocontinueExecute,theexecutionoftheafunctioniscompleteandreturntothebreakpointofthemainfunctiontocontinueexecution.
[Příklad]Výpočet=2∧2!+3∧2!
Thisquestioncanwritetwofunctions,oneisthefunctionf1usedtocalculatethesquarevalue,andtheotherisThefunctionf2usedtocalculatethefactorialvalue.Themainfunctionfirstadjustsf1tocalculatethesquarevalue,andthentakesthesquarevalueinf1astheactualparameter,callsf2tocalculatethefactorialvalue,andthenreturnstof1,thenreturnstothemainfunction,andcalculatesthecumulativesumintheloopprogram.
longf1(intp)
{intk;
delší;
longf2(int);
k=p*p;
r=f2(k);
returnr;}
longf2(intq)
p>{longc=1;
inti;
for(i=1;i<=q;i++)
c=c*i;
returnc;}
hlavní()
{inti;
longs=0;
p>for(i=2;i<=3;i++)
s=s+f1(i);
printf("\ns=%ld\n",s);}
Intheprogram,thefunctionsf1andf2arebothlongintegers,whicharedefinedbeforethemainfunction,sothereisnoneedtoexplainf1andf2inthemainfunction.Inthemainprogram,theexecutionloopprogramsequentiallycallsthevalueofiastheactualparametertocallthefunctionf1toobtainthevalueofi2.Inf1,acalltofunctionf2occursagain.Atthistime,thevalueofi2isusedasanactualparametertoadjustf2,andthecalculationofi2!iscompletedinf2.Afterf2isexecuted,theCvalue(iei2!)isreturnedtof1,andthenf1returnstothemainfunctiontoachieveaccumulation.Sofar,therequirementoftheproblemisrealizedbythenestedcallofthefunction.Becausethevalueisverylarge,thetypesoffunctionsandsomevariablesaredeclaredaslongintegers,otherwiseitwillcausecalculationerrors.
Aktuální implementace
Pointerregister
EBP
EBPistheso-calledframepointer,pointingtothecurrentactivityAbovetherecord(thebottomofthepreviousactivityrecord)
ESP
ESPistheso-calledstackpointer,whichpointstothebottomofthecurrentactivityrecord(bottomAnactivityrecordtobeinsertedatthetop)
Thevalueofthesetwopointersspecifiesthepositionofthecurrentactivityrecord
Předávání parametrů
PressfunctionparametersStack:moveax,dwordptr[n];(nisaparametrargument)
pusheax
Operace
Volání funkce provede následující operace:
⒈Posunoutbod rámečku na zásobník:pushebp
⒉ukazatel rámce musí být stejný jako ukazatel zásobníku:movebp,esp
⒊makethestackpointerdecrement,Thememoryaddressobtainedbysubtractionshouldbeableto(enough)beusedtostorethelocalstateofthecalledfunction:subesp,0CCh
Poznámka:0CChje 0xCC, které se liší podle konkrétní funkce.
Passinsavestate
pushebx;savethevalueofebxregister
pushesi;uložte hodnotu registru
pusshedi;Uložte hodnotu registru
Loadedi
leaedi,[ebp-0CCh];0cchivelikost aktuálního aktivního záznamu.
EDIje registr cílových indexů.
Obnovení stavu příchozích
00411417popedi
00411418popesi
popebx
stackMovethepointeruptorestorespace
addesp,0CCh
Funkce návratu úložiště pronajatého prostoru
Když se funkce vrátí, kompilátor a hardware provedou následující operace:
⒈Umístěte, aby byl bod zásobníku stejný jako ukazatel snímku: movesp,ebp
⒉Přesuňte ukazatel starého snímku ze zásobníku:popebp
⒊Return:ret
Příklad1
;voidfunction(intn);{pushebp
movebp, např
subesp,0CCh
pushebx
pushesi
pusdedi
leaedi,[ebp-0CCh]
movecx, 33h
moveax,0CCCCCCCCh
repstosdwordptres:[edi]
;chara=1;
movbyteptr[a],1
;if(n==0)návrat;
cmpdwordptr[n],0
jnefunction+2Ah(4113CAh)
jmpfunction+77h(411417h)
;printf("%d\t(0x%08x)\n",n,&n);
Movesi, např
leaeax,[n]
pusheax
movecx,dwordptr[n]
pushecx
pushoffsetstring"%d\t(0x%08x)\n"(415750h)
callwordptr[__imp__printf(4182B8h)]
addesp,0Ch
cmpesi, např
call@ILT+305(__RTC_CheckEsp)(411136h)
;funkce(n-1);
moveax,dwordptr[n]
subeax,1
pusheax
funkce volání (411041h)
addesp,4
;printf("----%d\t(0x%08x)\n",n,&n);
Movesi, např
leaeax,[n]
pusheax
movecx,dwordptr[n]
pushecx
pushoffsetstring"----%d\t(0x%08x)\n"(41573Ch)
callwordptr[__imp__printf(4182B8h)]
addesp,0Ch
cmpesi, např
call@ILT+305(__RTC_CheckEsp)(411136h);}
popedi
popesi
popebx
addesp,0CCh
cmpebp, esp
call@ILT+305(__RTC_CheckEsp)(411136h)
movesp,ebp
popebp
ret
Příklad2
117:bR=t1(p);
Kód sestavení je následující:
00401FB8movecx,dwordptr[ebp-8];zadejte parametr do registru ecx
00401FBBpushecx;parametr do zásobníku
00401FBCcall@ILT+10(t1)(0040100f);Volání funkce,do zásobníku bude vložena adresa dalšího řádku00401FC1
00401FC1addesp,4;Funkce se vrátí, bod zásobníku se zvýší o 4 a obnoví se na hodnotu 00401FB8
00401FC4movdwordptr[ebp-10h],eax;Získejte návratovou hodnotu funkce v jazyce vysoké úrovně z axa vložte do proměnné bR
Funkce t1 je následující:
125:BOOLt1(void*p)
126:{
00402030pushebp;ebpintostack
00402031přesunbp,zejména;ebppointsnahoruhromadyvtentočas
00402033subesp,44h;espsníží o jednu hodnotu a zdarma
p>00402036pushebx;Vložte hodnotytříregistrů do zásobníků, které můžete použít ve funkci
00402037pushesi;
00402038pushedi;
00402039leaedi,[ebp-44h];
0040203Cmovecx,11h;
00402041moveax,0CCCCCCCCCh;
00402046repstosdwordptr[edi];
127:int*q=(int*)p;;
00402048moveax,dwordptr[ebp+8];ebp+8 bodůpro zadání funkceNejnižší bitovou adresu parametru;
;jestliže je ebp+4,ukazuje na nejnižšíbitzvratnéadresyfunkce00401FC1,hodnotajeC1
0040204Bmovdwordptr[ebp-4],eax;
128:return0;
0040204Exoreax,eax;Otočná hodnota je umístěna v registru eax
129:}
00402050popedi;Tři registrační výlevky ze zásobníku
00402051popesi;
00402052popebx;
00402053movesp,ebp;esprestore
00402055popebp;ebpp vyskočí ze zásobníku a jeho hodnota se obnoví
00402056ret;Vraťte se na kódovou adresu uloženou v horní části zásobníku v čase:00401FC1
;soifyouareunluckyIfthereturnaddressismodified,theprogramwillbeunexpected
Výše uvedený kód sestavy je sestaven systémem VC++ 6.0.
ThesituationofthestackaftertheEBPisputintothestack:
Nízká a vysoká
↓↓
Paměťový zásobník adres
┆┆
0012F600├───────┤←edi=0012F600
││
0012F604├─┄┄┄┄─┤
││
││
┆44hmezera┆
┆┆
││
││
0012F640├─┄┄┄┄─┤
││
0012F644├───────┤←Ebpis přiřazený k bodu této jednotce, atthistimeebp=0012F644
│ACF61200│bpispřiřazenohodnotěpředtím
0012F648├────────┤
│C11F4000│Zpáteční adresa
0012F64C├─────────┤←ebp+8
│A0F61200│Hodnotaparametrufunkcep;
0012F650├─────────┤
││
├────────┤
┆┆
Note:Thememorystoragespacestackisarrangedfromhightolow,andtheaddressmarkedontheleftisthelowestaddressofthestorageunitatthebottomright.Forexample,0012F644pointstotheACbyteof0012F6AC,andACisatthetopofthestack.Thecontentinthememoryinthefigureiswrittenfromlowtohigh,"ACF61200"=0x0012F6AC
Vysvětlení
(1)Acprogramiscomposedofoneormoreprogrammodules,Eachprogrammoduleasasourceprogramfile.Forlargerprograms,yougenerallydon'twanttoputallthecontentinonefile,butputtheminseveralsourcefiles,andacprogramiscomposedofseveralsourceprogramfiles.Thismakesiteasytowriteandcompileseparately,andimprovedebuggingefficiency.Asourceprogramfilecanbesharedbymultiplecprograms.
(2)Asourceprogramfileiscomposedofoneormorefunctionsandotherrelatedcontent(suchasinstructions,datadeclarationsanddefinitions,etc.).Asourceprogramfileisacompilationunit,andthesubprogramiscompiledintheunitofthesourceprogramfile,notintheunitofthefunction.
(3)Theexecutionofthecprogramstartsfromthemainfunction.Ifyoucallotherfunctionsinthemainfunction,theprocessreturnstothemainfunctionafterthecall,andthewholeprogramendsinthemainfunction.
(4)Allfunctionsareparallel,thatis,whendefiningfunctions,theyareperformedseparatelyandareindependentofeachother.Afunctionisnotsubordinatetoanotherfunction,thatis,functionscannotbenesteddefinitions.Functionscancalleachother,butcannotcallthemainfunction.Themainfunctioniscalledbytheoperatingsystem.
(5)Z pohledu uživatele existují dva typy funkcí
a:libraryfunctions,whichareprovidedbythesystem,andusersdonotneedtodefinethembythemselves,butcanusethemdirectly.Itshouldbenotedthatthenumberandfunctionsoflibraryfunctionsprovidedbydifferentclanguagecompilationsystemswillbesomewhatdifferent,ofcourse,manybasicfunctionsarecommon.
b:Uživatelem definovaná funkce. Je to funkce, která řeší konkrétní potřeby zapékače.
(6)Podle tvaru funkcí jsou funkce rozděleny do dvou kategorií.
a:Funkce bez parametrů. Žádné funkce parametrů nemohou vrátit nebo vrátit hodnoty funkcí, ale obecně existuje více hodnot funkcí, které nelze vrátit zpět.
b:Functionwithparameters.Whencallingafunction,thecallingfunctionpassesdatatothecalledfunctionthroughparameterswhencallingthecalledfunction.Undernormalcircumstances,afunctionvaluewillbeobtainedwhenthecallingfunctionisexecuted,whichcanbeusedbythecallingfunction.