Tehtävä

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 29. maaliskuuta 2021 tarkistetusta versiosta . tarkastukset vaativat 23 muokkausta .

Assignment  on ohjelmoinnin sitova mekanismi, jonka avulla voit dynaamisesti muuttaa tietoobjektien nimien (yleensä muuttujien ) suhdetta niiden arvoihin. Tarkkaan ottaen arvojen muuttaminen on osoitusoperaation sivuvaikutus, ja monissa nykyaikaisissa ohjelmointikielissä toiminto myös itse palauttaa jonkin tuloksen (yleensä kopion määritetystä arvosta). Fyysisellä tasolla osoitusoperaation tulos on muistisolujen tai prosessorirekisterien kirjoittaminen ja uudelleenkirjoittaminen .

Toimeksianto on yksi keskeisistä imperatiivisten ohjelmointikielten rakenteista , joka toteutetaan tehokkaasti ja yksinkertaisesti nykyaikaisten tietokoneiden perustana olevalle von Neumann -arkkitehtuurille .

Olio-ohjelmointikielissä osoituksen semantiikka on aivan erilainen. Esimerkiksi Kotlin -kielellä kohdetta määritettäessä kopioidaan ja Rust -kielellä objektia siirretään (move-semantics) ja vanha nippu mitätöityy.

Logiikkaohjelmointi käyttää erilaista, algebrallista lähestymistapaa. Tässä ei ole tavallista ("tuhoista") tehtävää. On vain tuntemattomia, joita ei ole vielä laskettu, ja vastaavat tunnisteet osoittamaan näitä tuntemattomia. Ohjelma vain määrittää niiden arvot, ne itse ovat vakioita. Tietenkin toteutuksessa ohjelma kirjoittaa muistiin, mutta ohjelmointikielet eivät heijasta tätä, mikä antaa ohjelmoijalle mahdollisuuden työskennellä vakioarvojen tunnisteiden, ei muuttujien kanssa.

Puhdas toiminnallinen ohjelmointi ei käytä muuttujia, eikä se tarvitse nimenomaista määrityslauseketta.

Määritelmä

Yksinkertaisen tehtävän yleinen syntaksi on seuraava:

<lauseke vasemmalla> <tehtäväoperaattori> <lauseke oikealla>

"Vasemmanpuoleisen lausekkeen" tulee arvioinnin jälkeen johtaa dataobjektin sijaintiin, kohdemuuttujaan, sen muistisolun tunnisteeseen, johon tallennus tehdään. Tällaisia ​​viittauksia kutsutaan "vasemmiksi arvoiksi" ( englanniksi  lvalue ). Tyypillisiä esimerkkejä vasenkätisistä arvoista ovat muuttujan nimi ( x), polku nimiavaruudessa ja kirjastoissa olevaan muuttujaan ( Namespace.Library.Object.AnotherObject.Property), taulukon polku lausekkeella indeksin tilalla ( this.a[i+j*k]), mutta monimutkaisempia vaihtoehtoja annetaan myöhemmin tässä artikla.

"Oikealla oleva lauseke" on tavalla tai toisella ilmaistava tietoobjektille annettava arvo. Näin ollen vaikka saman muuttujan nimi olisi oikealla kuin vasemmalla, se tulkitaan eri tavalla - tällaisia ​​viittauksia kutsutaan "oikeanpuoleisiksi arvoiksi" ( englanniksi  rvalue ). Käytetty kieli asettaa lisärajoituksia lausekkeelle : näin ollen staattisesti kirjoitetuissa kielissä sillä on oltava sama tyyppi kuin kohdemuuttuja tai siihen valettu tyyppi; joissakin kielissä (esimerkiksi C tai Pythona=b=c ) lausekkeeseen voi sisältyä myös toinen määritysoperaattori ( ).

Ohjelmointikielissä yleisin tehtäväoperaattori on =, :=tai ←. Mutta erityistä syntaksia ei saa ottaa käyttöön - esimerkiksi Tcl : ssä :

aseta <kohdemuuttuja> <lauseke>

Tämä merkintätapa vastaa funktion kutsumista . Samoin vanhan tyylin COBOLissa :

KERRO 2 2:LLA ANNA NELJÄ.

Toimintaalgoritmi

Nimitys

Tehtäväsymbolin valinta on kiistanalainen kielisuunnittelijoiden keskuudessa. On olemassa mielipide, että symbolin =käyttö tehtävän antamisessa hämmentää ohjelmoijia ja herättää myös kysymyksen vertailuoperaattorin symbolin valinnasta , jota on vaikea ratkaista hyvin .

Siten Niklaus Wirth totesi [1] :

Tunnettu huono esimerkki on yhtäläisyysmerkin valinta tehtävää kuvaamaan, joka juontaa juurensa Fortranista vuonna 1957 ja jota monet kielenkehittäjät toistavat edelleen sokeasti. Tämä huono idea kumoaa ikivanhan perinteen käyttää " = "-merkkiä merkitsemään tasa-arvovertailua, predikaattia, jonka arvo on " tosi " tai " epätosi ". Mutta Fortranissa tämä symboli alkoi merkitä tehtävää, pakottamista tasa-arvoon. Tässä tapauksessa operandit ovat epätasaisessa paikassa: vasen operandi, muuttuja, on tehtävä yhtäläiseksi oikean operandin, lausekkeen kanssa. Joten x = y ei tarkoita samaa kuin y = x.

Alkuperäinen teksti  (englanniksi)[ näytäpiilottaa] Tunnettu esimerkki huonosta ideasta oli yhtäläisyysmerkin valinta osoittamaan tehtävää. Se juontaa juurensa Fortraniin vuonna 1957, ja kielisuunnittelijoiden armeijat ovat kopioineet sen. Miksi se on huono idea? Koska se kaataa vuosisadan vanhan perinteen antaa "=" tarkoittaa tasa-arvon vertailua, predikaattia, joka on joko tosi tai epätosi. Mutta Fortran teki sen tarkoittavan toimeksiantoa, tasa-arvon täytäntöönpanoa. Tässä tapauksessa operandit ovat eriarvoisessa asemassa: Vasen operandi (muuttuja) on tehtävä yhtä suureksi kuin oikea operandi (lauseke). x = y ei tarkoita samaa kuin y = x. [2]

Tämän Wirthin aseman toteutus voidaan katsoa, ​​että Pascal -kielessä , jonka kirjoittaja hän on, osoitusoperaattori on :=, kun taas vertailua varten sitä käytetään yksinkertaisesti =.

Tasa-arvooperaattorisymbolin valinnan kielellä, kun sitä käytetään =tehtävänä, päättää:

Tasa-arvon merkintä C == :ssä aiheuttaa usein virheitä, koska osoitusta on mahdollista käyttää ohjausrakenteissa, mutta muilla kielillä ongelma ratkaistaan ​​ottamalla käyttöön lisärajoituksia.

Esimerkiksi PL/1 - kielilausekkeessa :

A = B = C

muuttujalle Аannetaan relaatiolausekkeen Boolen arvoВ = С . Tällainen merkintä heikentää luettavuutta ja sitä käytetään harvoin.

Semantiset ominaisuudet

Ei suinkaan aina "intuitiivinen" (pakollisten kielten ohjelmoijille) tapa tulkita tehtävä on ainoa oikea ja mahdollinen.

Pakollisten kielten syntaksista ei aina ole mahdollista ymmärtää, kuinka tehtävän semantiikka on toteutettu , ellei sitä ole erikseen määritelty kielessä.

Esimerkiksi Forthissa ennen määritystä muuttujan arvon ja osoitteen täytyy mennä tietopinoon, ja tämä voidaan tehdä kauan ennen varsinaisen osoituksen suorittamista.

Esimerkki:

\ Määrittele muuttuja AAA ja anna sille arvo 10 seuraavalla rivillä MUUTTUVA AAA 10 AAA!

Sama asia hieman eri tavalla:

kymmenen MUUTTUVA AAA AAA! Epäselvyys

Harkitse esimerkkiä:

X = 2+1

Tämä voidaan ymmärtää siten, että "laskennan tulos 2+1 (eli 3) on määritetty muuttujalle X" tai "operaatio 2+1 on määritetty muuttujalle X". Jos kieli on staattisesti kirjoitettu , siinä ei ole epäselvyyttä, vaan se ratkaistaan ​​muuttujan tyypin mukaan X("kokonaisluku" tai "operaatio"). Prologissa kirjoittaminen on dynaamista , joten määritystoimintoja on kaksi:  - vastaavan arvon määrittäminen ja  - kuvion antaminen . Tässä tapauksessa: is=

X on 2 + 1, X = 3 X = 2+1, X = 3

Ensimmäinen sekvenssi tunnistetaan tosi, toinen epätosi.

Teksti

Kun käsitellään suurikokoisia ja monimutkaisia ​​​​rakenteita, monet kielet käyttävät niin kutsuttua " viite semantiikkaa ". Tämä tarkoittaa, että osoitusta klassisessa mielessä ei tapahdu, vaan kohdemuuttujan arvon katsotaan olevan samassa paikassa kuin lähdemuuttujan arvo. Esimerkiksi ( Python ):

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

Sen jälkeen sillä bon arvo [1, 1000, 3] - yksinkertaisesti siksi, että itse asiassa sen arvo on arvo a. Viittausten määrää samaan tietoobjektiin kutsutaan sen kardinaalisuudesta, ja itse objekti tapetaan (tuhotetaan tai annetaan roskienkerääjälle ), kun sen kardinaliteetti saavuttaa nollan. Alemman tason ohjelmointikielet (kuten C ) antavat ohjelmoijalle mahdollisuuden valvoa, käytetäänkö osoittimen semantiikkaa vai kopiointisemantiikkaa.

Toiminnan korvaaminen

Monet kielet tarjoavat mahdollisuuden muuttaa toimeksiannon merkitystä joko ominaisuusmekanismin kautta tai ylikuormittamalla toimeksiantooperaattoria. Korvaaminen voi olla tarpeen määritetyn arvon oikeellisuuden tarkistamiseksi tai muiden lisätoimintojen suorittamiseksi. Tehtäväoperaattorin ylikuormitusta käytetään usein "syvän kopion" tuottamiseen, toisin sanoen arvojen kopioimiseen viittausten sijaan, jotka kopioidaan oletuksena monilla kielillä.

Tällaiset mekanismit mahdollistavat mukavuuden tarjoamisen työssä, joten ohjelmoijalle ei ole eroa sisäänrakennetun operaattorin ja ylikuormitetun operaattorin käytön välillä. Samasta syystä ongelmat ovat mahdollisia, koska ylikuormitetun operaattorin toimet voivat olla täysin erilaisia ​​​​kuin oletusoperaattorin toiminnot, ja funktiokutsu ei ole ilmeinen ja se voidaan helposti sekoittaa sisäänrakennetuksi toiminnoksi.

Laajennetut mallit

Koska määritysoperaattoria käytetään laajalti, ohjelmointikielten kehittäjät yrittävät kehittää uusia rakenteita yksinkertaistaakseen tyypillisten operaatioiden kirjoittamista (lisätäkseen kieleen ns. " syntaktisen sokerin "). Lisäksi matalan tason ohjelmointikielissä sisällyttämiskriteerinä on usein kyky kääntää tehokkaaksi suoritettavaksi koodiksi. [3] C -kieli on erityisen kuuluisa tästä ominaisuudesta .

Useita kohteita

Yksi vaihtoehto yksinkertaiselle operaattorille on kyky määrittää lausekkeen arvo useille objekteille . Esimerkiksi PL/1 :ssä operaattori

SUMMA, YHTEENSÄ = 0

määrittää samanaikaisesti nollan muuttujille SUMja TOTAL. Adassa osoitus on myös lause, ei lauseke, joten usean tehtävän merkintä on:

SUMMA, YHTEENSÄ: Kokonaisluku := 0;

Pythonissa vastaavalla tehtävällä on seuraava syntaksi:

summa = yhteensä = 0

Toisin kuin PL/1, Ada ja Python, joissa usean osoituksen katsotaan olevan vain lyhenne merkintänä, C :ssä , Lisp -muodossa ja muissa tällä syntaksilla on tiukka perusta: osoitusoperaattori yksinkertaisesti palauttaa sille määritetyn arvon (katso edellä). Eli viimeinen esimerkki on itse asiassa:

summa = (yhteensä = 0)

Tällainen rivi toimii C:ssä (jos lisäät puolipisteen loppuun), mutta aiheuttaa virheen Pythonissa.

Rinnakkaistehtävä

Jotkut kielet, kuten Ruby ja Python , tukevat laajennettua määrityssyntaksia, jota kutsutaan rinnakkaismääritykseksi:

a , b = 1 , 11

Uskotaan, että tällainen määritys suoritetaan samanaikaisesti ja rinnakkain , mikä mahdollistaa lyhyesti tämän rakenteen avulla kahden muuttujan arvojen vaihtamisen.

Kirjoittaminen rinnakkaistehtävällä "Perinteinen" tehtävä: vaatii lisämuuttujan ja kolme toimintoa "Taloudellinen" tehtävä: ei vaadi lisämuuttujaa, mutta sisältää myös kolme toimintoa Vielä "taloudellisempi" tehtävä: ei vaadi lisämuuttujaa, toimii bittioperaatioiden kanssa
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

Toiseksi viimeinen aritmeettinen vaihtoehto ei ole turvallinen ohjelmointikielissä tai laitteistoalustoissa, jotka tarkistavat aritmeettisia ylivuotoja .

Jälkimmäinen vaihtoehto toimii vain tyypeillä, jotka tukevat bittikohtaisia ​​toimintoja (esimerkiksi C#double -kääntäjä ei salli muuttujien arvojen vaihtamista tällä tavalla).

Joillakin kielillä (kuten PHP ) on rakenteita rinnakkaismäärittelyn simuloimiseksi:

lista ( $a , $b ) = array ( $b , $a );

Ehdolliset tavoitteet

Jotkut ohjelmointikielet, kuten C++ , sallivat ehdolliset kohteet tehtävälausekkeissa. Esimerkiksi lauseke:

( lippu ? count1 : count2 ) = 0 ;

antaa arvon 0muuttujalle count1if , ja jos . flag==truecount2flag==false

Toinen ehdollisen tehtävän muunnos ( Ruby ):

a ||= 10

Tämä konstruktio antaa aarvon muuttujalle vain, jos arvoa ei ole vielä määritetty tai se on yhtä suuri kuin false.

Yhdistetyt lausunnot

Yhdistetyn osoitusoperaattorin avulla voit lyhentää yleisesti käytettyä tehtävän muotoa. Tällä menetelmällä voit lyhentää tehtävän merkintää, joka käyttää kohdemuuttujaa ensimmäisenä operandina lausekkeen oikealla puolella, esimerkiksi:

a = a + b

C -yhdisteen osoitusoperaattorin syntaksi on halutun binäärioperaattorin ja =. Esimerkiksi seuraavat merkinnät ovat vastaavia

sum += value; sum = sum + value;

Ohjelmointikielillä, jotka tukevat yhdistelmäoperaattoreita ( C++ , C# , Python , Java jne.), on yleensä versiot useimpien näiden kielten binäärioperaattoreille+= ( , -=, &=jne.).

Unaarioperaattorit

C -perheen kielissä on neljä unaarista (eli ottamalla yksi argumentti) aritmeettista operaattoria lukujen lisäämiseksi ja vähentämiseksi yhdellä: kaksi " "-operaattoria ja kaksi " "-operaattoria. Operaattoreita voidaan kirjoittaa ennen operandia (etuliite) tai sen jälkeen (postfix tai suffiksi). Etuliitteen ja jälkiliitteen operaattorit eroavat arviointijärjestyksessä. Etuliiteoperaattorit muuttavat numeroa yhdellä ja palauttavat muuttuneen numeron. Postfix-operaattorit tallentavat luvun väliaikaiseen muuttujaan, muokkaavat alkuperäistä numeroa ja palauttavat väliaikaisen muuttujan arvon. ++--

Esimerkki operaattorin käytöstä : ++

Muuttujan arvon kasvattaminen yhdellä Vastaava merkintä
count ++; count = count + 1;

Vaikka se ei näytä tehtävältä, se on. Yllä olevan käskyn suorittamisen tulos on sama kuin tehtävän suorittamisen tulos.

Operaattoreita " " kutsutaan lisäysoperaattoreiksi ja " " -operaattoreita kutsutaan dekrementiooperaattoreiksi. Operaattoreita käytetään usein C-kielessä käsiteltäessä osoittimia ja taulukkoindeksejä . ++--

Toteutus

Nykyaikaisten tietokoneiden toiminta koostuu tietojen lukemisesta muistista tai laitteesta rekistereihin, tietojen suorittamisesta ja kirjoittamisesta muistiin tai laitteeseen. Päätoiminto tässä on tiedonsiirto (rekistereistä muistiin, muistista rekisteriin, rekisteristä rekisteriin). Näin ollen se ilmaistaan ​​suoraan nykyaikaisten prosessorien ohjeilla . Joten x86 -arkkitehtuurille (kaikki alla olevat komennot koskevat myös tätä arkkitehtuuria) tämä on operaatio movja sen lajikkeet erikokoisten tietojen lähettämiseen. Osoitustoiminto (tietojen siirto muistisolusta toiseen) toteutetaan käytännössä suoraan tällä komennolla. Yleisesti ottaen tiedonsiirron suorittamiseen muistissa tarvitaan kaksi käskyä: muistista rekisteriin ja rekisteristä muistiin siirto, mutta optimoinnilla käskyjen määrää voidaan useimmissa tapauksissa vähentää.

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

Esimerkki koodin luomisesta ( GCC ), kaksi
määritysohjetta

Katso myös

Muistiinpanot

  1. Niklaus Wirth . Hyviä ideoita: katselu lasin läpi . Per. Sergei Kuznetsov (2006). Haettu 23. huhtikuuta 2006. Arkistoitu alkuperäisestä 27. syyskuuta 2011.
  2. Niklaus Wirth. Hyviä ideoita katselasin läpi . Haettu 4. joulukuuta 2010. Arkistoitu alkuperäisestä 25. kesäkuuta 2012.
  3. Optimointia varten monet toiminnot yhdistetään toimeksiantoon. Pikakirjoituksilla on usein vastine koneohjeissa. Yhdellä lisääminen toteutetaan siis konekäskyllä inc​​, vähennys yhdellä - dec, yhteenlasku osoituksella - add, vähennys osoituksella - sub, ehdollinen siirtokäsky - cmovajne cmovno.

Kirjallisuus

  • Robert W. Sebesta. Ohjelmointikielten peruskäsitteet\u003d Ohjelmointikielten käsitteet. - 5. painos - M .: Williams , 2001. - 672 s. - ISBN 0-201-75295-6 .
  • M. Ben-Ari. Ohjelmointikielet. Käytännön vertaileva analyysi. - M.: Mir, 2000. - 366 s. s. 71-74.
  • V. E. Wolfenhagen. Ohjelmointikielten suunnittelu. Kuvausmenetelmät. - M .: JSC Center YurInfoR, 2001. - 276 s. ISBN 5-89158-079-9 . s. 128-131.
  • E. A. Opaleva, V. P. Samoilenko. Ohjelmointikielet ja käännösmenetelmät. - Pietari: BHV-Petersburg, 2005. - 480 s. ISBN 5-94157-327-8 . s. 74-75.
  • T. Pratt, M. Zelkowitz. Ohjelmointikielet: kehitys ja toteutus. - 4. painos - Pietari: Pietari, 2002. - 688 s. ISBN 5-318-00189-0 , ISBN 0-13-027678-2 . s. 201-204.