Opgave

Den aktuelle version af siden er endnu ikke blevet gennemgået af erfarne bidragydere og kan afvige væsentligt fra den version , der blev gennemgået den 29. marts 2021; checks kræver 23 redigeringer .

Tildeling  er en bindende mekanisme i programmering , der giver dig mulighed for dynamisk at ændre forholdet mellem navnene på dataobjekter (normalt variabler ) med deres værdier. Strengt taget er ændring af værdier en bivirkning af tildelingsoperationen, og i mange moderne programmeringssprog returnerer selve operationen også et resultat (normalt en kopi af den tildelte værdi). På det fysiske niveau er resultatet af en tildelingsoperation at skrive og omskrive hukommelsesceller eller processorregistre .

Opgave er en af ​​de centrale konstruktioner i imperative programmeringssprog , implementeret effektivt og enkelt på von Neumann-arkitekturen , der er grundlaget for moderne computere .

I objektorienterede programmeringssprog er opgavens semantik ret anderledes. For eksempel i Kotlin -sproget kopieres objektet ved tildeling, og i Rust -sproget flyttes objektet (move-semantics), og det gamle bundt bliver ugyldigt.

Logisk programmering tager en anden, algebraisk tilgang. Der er ingen almindelig ("destruktiv") opgave her. Der er kun ukendte, der endnu ikke er blevet beregnet, og tilsvarende identifikatorer til at angive disse ukendte. Programmet bestemmer kun deres værdier, de er selv konstante. Selvfølgelig skriver programmet i implementeringen til hukommelsen, men programmeringssprog afspejler ikke dette, hvilket giver programmøren mulighed for at arbejde med identifikatorer med konstante værdier og ikke med variabler.

Ren funktionel programmering bruger ikke variabler og behøver ikke en eksplicit opgaveerklæring.

Definition

Den generelle syntaks for en simpel opgave er som følger:

<udtryk til venstre> <tildelingsoperator> <udtryk til højre>

"Udtrykket til venstre" skal efter evaluering føre til placeringen af ​​dataobjektet, til målvariablen, identifikatoren for den hukommelsescelle, som optagelsen vil blive foretaget til. Sådanne referencer kaldes "venstre-værdier" ( engelsk  lvalue ). Typiske eksempler på en venstrehåndsværdi er et variabelnavn ( x), en sti til en variabel i navneområde og biblioteker ( Namespace.Library.Object.AnotherObject.Property), en matrixsti med et udtryk i stedet for indekset ( this.a[i+j*k]), men mere komplekse muligheder gives senere i denne artikel.

"Udtrykket til højre" skal på den ene eller anden måde angive den værdi, der skal tildeles dataobjektet. Selv hvis navnet på den samme variabel står til højre som til venstre, fortolkes det således forskelligt - sådanne referencer kaldes "højrehåndsværdier" ( engelsk  rvalue ). Det anvendte sprog pålægger udtrykket yderligere begrænsninger : i statisk indtastede sprog skal det altså have samme type som målvariablen, eller en type, der er støbt til den; på nogle sprog (for eksempel C eller Python ), kan en anden tildelingsoperator ( a=b=c) også inkluderes i udtrykket.

Den mest almindelige opgaveoperatør i programmeringssprog er =, :=eller ←. Men speciel syntaks kan ikke introduceres - for eksempel i Tcl :

sæt <målvariabel> <udtryk>

Denne notation svarer til at kalde en funktion . På samme måde i gammeldags COBOL :

GIVER 2 MED 2, GI FIRE.

Operationsalgoritme

Betegnelse

Valget af opgavesymbolet er et spørgsmål om kontrovers blandt sprogdesignere. Der er en opfattelse af, at brugen af ​​et symbol =til opgave forvirrer programmører , og rejser også spørgsmålet om at vælge et symbol for sammenligningsoperatøren , hvilket er svært at løse godt .

Således udtalte Niklaus Wirth [1] :

Et velkendt dårligt eksempel er valget af et lighedstegn til at betegne en opgave, som går tilbage til Fortran i 1957 og stadig blindt gentages af en masse sprogudviklere. Denne dårlige idé vælter den ældgamle tradition med at bruge tegnet " = " til at angive en lighedssammenligning, et prædikat, der evalueres til " sandt " eller " falsk ". Men i Fortran begyndte dette symbol at betegne tildeling, tvang til ligestilling. I dette tilfælde er operanderne i en ulige position: den venstre operand, variablen, skal gøres lig med den højre operand, udtrykket. Så x = y betyder ikke det samme som y = x.

Originaltekst  (engelsk)[ Visskjule] Et berygtet eksempel på en dårlig idé var valget af lighedstegnet til at betegne opgave. Det går tilbage til Fortran i 1957 og er blindt blevet kopieret af hære af sprogdesignere. Hvorfor er det en dårlig idé? Fordi det vælter en århundrede gammel tradition at lade "=" betegne en sammenligning for lighed, et prædikat som enten er sandt eller falsk. Men Fortran fik det til at betyde overdragelse, håndhævelse af lighed. I dette tilfælde er operanderne på ulige fod: Den venstre operand (en variabel) skal gøres lig med den højre operand (et udtryk). x = y betyder ikke det samme som y = x. [2]

Implementeringen af ​​denne holdning af Wirth kan anses for, at i Pascal -sproget , som han er forfatter til, er opgaveoperatøren :=, mens den til sammenligning blot bruges =.

Valget af lighedsoperatørsymbolet på sproget, når det bruges =som en opgave, afgøres af:

Notation af lighed i C == er en kilde til hyppige fejl på grund af muligheden for at bruge tildeling i kontrolkonstruktioner, men på andre sprog løses problemet ved at indføre yderligere begrænsninger.

For eksempel i PL/1 sprogudtrykket :

A = B = C

variablen Аtildeles den boolske værdi af relationsudtrykket В = С. En sådan notation fører til nedsat læsbarhed og bruges sjældent.

Semantiske træk

Langt fra altid "intuitiv" (for programmører af imperative sprog) måde at fortolke opgaven på er den eneste sande og mulige.

Ud fra den syntaks, der bruges i imperative sprog, er det ikke altid muligt at forstå, hvordan opgavesemantikken er implementeret, medmindre det er eksplicit defineret i sproget.

For eksempel, i Forth , før tildeling, skal værdien og adressen på en variabel gå ind i datastakken, og dette kan gøres længe før den faktiske tildeling udføres.

Eksempel:

\ Definerer variablen AAA og tildeler den værdien 10 i næste linje VARIABEL AAA 10 AAA!

Det samme lidt anderledes:

ti VARIABEL AAA AAA! Tvetydighed

Overvej et eksempel:

X=2+1

Dette kan forstås som "resultatet af beregningen 2+1 (dvs. 3) er tildelt en variabel X" eller som "operationen 2+1 er tildelt en variabel X". Hvis sproget er statisk skrevet , så er der ingen tvetydighed, det løses af typen af ​​variablen X("heltal" eller "operation"). I Prolog er skrivning dynamisk , så der er to tildelingsoperationer: is - tildeling af en tilsvarende værdi og = - tildeling af et mønster. I dette tilfælde:

X er 2 + 1, X = 3 X=2+1, X=3

Den første sekvens vil blive genkendt som sand, den anden - falsk.

Tekst

Når man beskæftiger sig med objekter af store størrelser og kompleks struktur, bruger mange sprog den såkaldte " referencesemantik ". Det betyder, at tildeling i klassisk forstand ikke forekommer, men værdien af ​​målvariablen anses for at være placeret samme sted som værdien af ​​kildevariablen. For eksempel ( Python ):

a = [1, 2, 3] b = a a[1] = 1000

Derefter bvil den have en værdi [1, 1000, 3] - simpelthen fordi dens værdi faktisk er værdien af a​​. Antallet af referencer til det samme dataobjekt kaldes dets kardinalitet, og selve objektet bliver dræbt (ødelagt eller givet til skraldeopsamleren ), når dets kardinalitet når nul. Programmeringssprog på lavere niveau (såsom C ) giver programmøren mulighed for eksplicit at kontrollere, om pointer-semantik eller kopi-semantik bruges.

Operation substitution

Mange sprog giver mulighed for at ændre betydningen af ​​en opgave, enten gennem ejendomsmekanismen eller gennem overbelastning af opgaveoperatøren. Substitution kan være nødvendig for at udføre kontrol af gyldigheden af ​​den tildelte værdi eller andre yderligere operationer. Overbelastning af opgaveoperatøren bruges ofte til at give en "dyb kopi", det vil sige kopiering af værdier i stedet for referencer, som kopieres som standard på mange sprog.

Sådanne mekanismer gør det muligt at give bekvemmelighed på arbejdet, så for en programmør er der ingen forskel mellem at bruge en indbygget operatør og en overbelastet. Af samme grund er problemer mulige, da den overbelastede operatørs handlinger kan være helt anderledes end standardoperatørens handlinger, og funktionskaldet er ikke indlysende og let kan forveksles med en indbygget operation.

Udvidede designs

Da opgaveoperatøren er meget udbredt, forsøger programmeringssprogsudviklere at udvikle nye konstruktioner for at forenkle skrivningen af ​​typiske operationer (for at tilføje det såkaldte " syntaktiske sukker " til sproget). Derudover er inklusionskriteriet i programmeringssprog på lavt niveau ofte evnen til at kompilere til effektiv eksekverbar kode. [3] C -sproget er især berømt for denne ejendom .

Flere mål

Et alternativ til den simple operator er muligheden for at tildele værdien af ​​et udtryk til flere objekter . For eksempel i PL/1 er operatøren

SUM, TOTAL = 0

tildeler samtidigt nul til variablerne SUMog TOTAL. I Ada er opgave også et udsagn, ikke et udtryk, så notationen for flere tildelinger er:

SUM, TOTAL: Heltal := 0;

En lignende opgave i Python har følgende syntaks:

sum = total = 0

I modsætning til PL/1, Ada og Python, hvor multiple tildelinger kun betragtes som en stenografi, i C , Lisp og andre, har denne syntaks et strengt grundlag: tildelingsoperatoren returnerer simpelthen den værdi, der er tildelt den (se ovenfor). Så det sidste eksempel er faktisk:

sum = (total = 0)

En linje som denne vil fungere i C (hvis du tilføjer et semikolon i slutningen), men vil forårsage en fejl i Python.

Parallel tildeling

Nogle sprog, såsom Ruby og Python , understøtter en udvidet tildelingssyntaks kaldet parallel tildeling:

a , b = 1 , 11

Det antages, at en sådan opgave udføres samtidigt og parallelt , hvilket gør det muligt kort at implementere ved hjælp af denne konstruktion operationen med at udveksle værdierne af to variable.

Skrivning ved hjælp af parallel tildeling "Traditionel" tildeling: kræver en ekstra variabel og tre operationer "Økonomisk" opgave: kræver ikke en ekstra variabel, men indeholder også tre operationer Endnu mere "økonomisk" tildeling: kræver ikke en ekstra variabel, fungerer med bitoperationer
a, b = b, a t = a a = b b=t a = a + b b = a - b a = a - b a ^= b b ^= a a ^= b

Den næstsidste aritmetiske mulighed er usikker i programmeringssprog eller hardwareplatforme, der kontrollerer for aritmetiske overløb .

Sidstnævnte mulighed fungerer kun med typer, der understøtter bitvise operationer (for eksempel vil C#double -kompileren ikke tillade dig at udveksle variable værdier på denne måde).

Nogle sprog (såsom PHP ) har konstruktioner til at simulere parallel tildeling:

liste ( $a , $b ) = matrix ( $b , $a );

Betingede mål

Nogle programmeringssprog, såsom C++ , tillader betingede mål i opgavesætninger. For eksempel udtrykket:

( flag ? tæll1 : tæl2 ) = 0 ;

vil tildele en værdi til 0variablen count1if , og if . flag==truecount2flag==false

En anden variant af betinget tildeling ( Ruby ):

a ||= 10

Denne konstruktion tildeler kun en aværdi til en variabel, hvis værdien endnu ikke er blevet tildelt eller er lig med false.

Sammensatte udsagn

Operatoren for sammensat tildeling giver dig mulighed for at forkorte en almindeligt brugt tildelingsform. Ved at bruge denne metode kan du forkorte notationen for en tildeling, der bruger målvariablen som den første operand på højre side af udtrykket, for eksempel:

a = a + b

Syntaksen for C -sammensatte tildelingsoperatoren er foreningen af ​​den ønskede binære operator og =. For eksempel er følgende poster tilsvarende

sum += value; sum = sum + value;

Programmeringssprog, der understøtter sammensatte operatorer ( C++ , C# , Python , Java osv.) har normalt versioner for de fleste af disse sprogs binære operatorer+= ( ,, -=osv &=.).

Unære operatorer

På sprogene i C -familien er der fire unære (det vil sige at tage et argument) aritmetiske operatorer til at øge og dekrementere tal med én: to " "-operatorer og to " "-operatorer. Operatorer kan skrives før operanden (præfiks) eller efter den (postfix eller suffiks). Præfiks- og postfix-operatorer er forskellige i evalueringsrækkefølgen. Præfiksoperatører ændrer et tal med én og returnerer det ændrede nummer. Postfix-operatører gemmer et tal i en midlertidig variabel, ændrer det oprindelige tal og returnerer værdien af ​​den midlertidige variabel. ++--

Et eksempel på brug af operatoren : ++

Forøgelse af værdien af ​​en variabel med én Tilsvarende notation
count ++; count = count + 1;

Selvom det ikke ligner en opgave, er det det. Resultatet af udførelsen af ​​ovenstående erklæring er det samme som resultatet af udførelsen af ​​opgaven.

Operatørerne " " kaldes inkrementoperatorer, og " "-operatorerne kaldes dekrementeringsoperatorer. Operatorer bruges ofte i C-sproget, når de håndterer pointere og array- indekser . ++--

Implementering

Betjening af moderne computere består i at læse data fra hukommelsen eller enheden ind i registre, udføre operationer på disse data og skrive til hukommelsen eller enheden. Hovedoperationen her er dataoverførsel (fra registre til hukommelse, fra hukommelse til register, fra register til register). Derfor udtrykkes det direkte af instruktionerne fra moderne processorer . Så for x86- arkitekturen (alle kommandoerne nedenfor gælder også for denne arkitektur), er dette en operation movog dens varianter til at sende data af forskellige størrelser. Tildelingsoperationen (overførsel af data fra en hukommelsescelle til en anden) implementeres praktisk talt direkte af denne kommando. Generelt kræves der to instruktioner for at udføre en dataoverførsel i hukommelsen: en hukommelse-til-register-bevægelse og en register-til-hukommelse-bevægelse, men med optimeringer kan antallet af instruktioner reduceres i de fleste tilfælde.

movl -4(%ebp), %
eax movl %eax, 8(%ebp)

Eksempel på kodegenerering ( GCC ), to
instruktioner til tildeling

Se også

Noter

  1. Niklaus Wirth . Gode ​​ideer: Se gennem brillerne . Om. Sergei Kuznetsov (2006). Hentet 23. april 2006. Arkiveret fra originalen 27. september 2011.
  2. Niklaus Wirth. Gode ​​ideer gennem skueglasset . Hentet 4. december 2010. Arkiveret fra originalen 25. juni 2012.
  3. For optimeringsformål kombineres mange operationer med tildeling. Stenografiopgaver har ofte en ækvivalent i maskininstruktioner. Så en stigning med én implementeres af maskininstruktionen inc, reduktion med én - dec, addition med tildeling - add, subtraktion med tildeling - , subbetingede overførselsinstruktioner - osv.cmovacmovno

Litteratur

  • Robert W. Sebesta. Grundlæggende begreber for programmeringssprog \u003d Begreber for programmeringssprog. - 5. udg. - M. : Williams , 2001. - 672 s. - ISBN 0-201-75295-6 .
  • M. Ben-Ari. Programmeringssprog. Praktisk komparativ analyse. — M.: Mir, 2000. — 366 s. s. 71-74.
  • V. E. Wolfenhagen. Design af programmeringssprog. Beskrivelsesmetoder. - M .: JSC Center YurInfoR, 2001. - 276 s. ISBN 5-89158-079-9 . s. 128-131.
  • E. A. Opaleva, V. P. Samoilenko. Programmeringssprog og oversættelsesmetoder. - St. Petersborg: BHV-Petersburg, 2005. - 480 s. ISBN 5-94157-327-8 . s. 74-75.
  • T. Pratt, M. Zelkowitz. Programmeringssprog: udvikling og implementering. - 4. udg. - St. Petersborg: Peter, 2002. - 688 s. ISBN 5-318-00189-0 , ISBN 0-13-027678-2 . s. 201-204.