Feladat

Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2021. március 29-én felülvizsgált verziótól ; az ellenőrzések 23 szerkesztést igényelnek .

A hozzárendelés  egy kötési mechanizmus a programozásban , amely lehetővé teszi az adatobjektumok (általában változók ) nevének és értéküknek a kapcsolatának dinamikus megváltoztatását. Szigorúan véve az értékek megváltoztatása a hozzárendelési művelet mellékhatása, és sok modern programozási nyelvben maga a művelet is visszaad valamilyen eredményt (általában a hozzárendelt érték másolatát). Fizikai szinten egy hozzárendelési művelet eredménye a memóriacellák vagy processzorregiszterek írása és átírása .

A hozzárendelés az imperatív programozási nyelvek egyik központi konstrukciója , amelyet hatékonyan és egyszerűen a modern számítógépek alapját képező Neumann-architektúrán valósítanak meg .

Az objektum-orientált programozási nyelvekben a hozzárendelés szemantikája egészen más. Például a Kotlin nyelvben hozzárendeléskor az objektumot másolják, a Rust nyelvben pedig az objektumot elmozdítják (move-semantics), és a régi köteg érvénytelenné válik.

A logikai programozás más, algebrai megközelítést alkalmaz. Itt nincs szokványos ("destruktív") megbízás. Csak olyan ismeretlenek vannak, amelyeket még nem számítottak ki, és ezeknek az ismeretleneknek megfelelő azonosítók . A program csak az értékeiket határozza meg, ők maguk állandóak. Természetesen a megvalósítás során a program a memóriába ír, de a programozási nyelvek ezt nem tükrözik, lehetőséget adva a programozónak , hogy állandó értékek azonosítóival dolgozzon, és nem változókkal.

A tiszta funkcionális programozás nem használ változókat, és nincs szüksége kifejezett hozzárendelési utasításra.

Definíció

Egy egyszerű feladat általános szintaxisa a következő:

<kifejezés a bal oldalon> <hozzárendelési operátor> <kifejezés a jobb oldalon>

A "baloldali kifejezés" a kiértékelés után az adatobjektum helyéhez, a célváltozóhoz, a memóriacella azonosítójához kell, hogy vezessen, amelybe a felvétel készül. Az ilyen hivatkozásokat "baloldali értékeknek" ( angolul  lvalue ) nevezik. A bal oldali értékek tipikus példái a változó neve ( x), egy változó elérési útja a névtérben és a könyvtárakban ( Namespace.Library.Object.AnotherObject.Property), egy tömb elérési útja egy kifejezéssel az index helyén ( this.a[i+j*k]), de az összetettebb opciókat később adjuk meg. cikk.

A "jobboldali kifejezésnek" így vagy úgy kell jelölnie az adatobjektumhoz rendelendő értéket. Így még akkor is, ha ugyanannak a változónak a neve található a jobb oldalon, mint a bal oldalon, másként értelmezik – az ilyen hivatkozásokat "jobboldali értékeknek" ( angolul  rvalue ) nevezik. A használt nyelv további megszorításokat támaszt a kifejezéssel kapcsolatban : így a statikusan beírt nyelvekben a célváltozóval azonos típusúnak kell lennie, vagy típusnak kell szerepelnie; bizonyos nyelveken (például C vagy Python ) egy másik hozzárendelési operátor ( a=b=c) is szerepelhet a kifejezésben.

A programozási nyelvekben a leggyakoribb hozzárendelési operátor a =, :=vagy ←. De speciális szintaxist nem lehet bevezetni - például a Tcl -ben :

állítsa be a <célváltozót> <kifejezést>

Ez a jelölés egyenértékű egy függvény meghívásával . Hasonlóképpen a régi stílusú COBOL -ban :

SZOROZZ 2-T 2-VEL, NEGYET ADVA.

Műveleti algoritmus

Megnevezés

A hozzárendelés szimbólumának megválasztása vita tárgya a nyelvtervezők körében. Egyes vélemények szerint a szimbólumok =hozzárendelési használata megzavarja a programozókat , és felveti az összehasonlító operátor szimbólumválasztásának kérdését is , amit nehéz jól megoldani .

Így Niklaus Wirth kijelentette [1] :

Jól ismert rossz példa az egyenlőségjel választása a feladat megjelölésére, amely Fortran 1957-ig nyúlik vissza, és még mindig vakon ismételgeti a nyelvfejlesztők tömege. Ez a rossz ötlet megdönti azt az ősrégi hagyományt, hogy a „ = ” jelet egy egyenlőség-összehasonlítás jelölésére használjuk, egy olyan állítmányt, amely „ igazra ” vagy „ hamisra ” értékel. De Fortranban ez a szimbólum a megbízást, az egyenlőségre való kényszert kezdte jelölni. Ebben az esetben az operandusok egyenlőtlen helyzetben vannak: a bal oldali operandust, a változót egyenlővé kell tenni a jobb oldali operandusszal, a kifejezéssel. Tehát az x = y nem ugyanazt jelenti, mint az y = x.

Eredeti szöveg  (angol)[ showelrejt] A rossz ötlet hírhedt példája volt az egyenlőségjel kiválasztása a hozzárendelés jelölésére. Az 1957-es Fortranig nyúlik vissza, és vakon másolták nyelvtervezők seregei. Miért rossz ötlet? Mert megdönt egy évszázados hagyományt, hogy a „=” az egyenlőség összehasonlítását jelölje, egy állítmányt, amely igaz vagy hamis. De Fortran a megbízást, az egyenlőség érvényesítését jelentette. Ebben az esetben az operandusok egyenlőtlenül állnak: A bal oldali operandust (változót) egyenlővé kell tenni a jobb oldali operandusszal (kifejezéssel). x = y nem ugyanazt jelenti, mint y = x. [2]

Wirth ezen álláspontjának megvalósítása úgy tekinthető, hogy a Pascal nyelvben , amelynek ő a szerzője, a hozzárendelés operátora :=, míg összehasonlítás céljából egyszerűen =.

Az egyenlőség operátor szimbólum kiválasztását a nyelvben, ha =hozzárendelésként használják, a következők döntik el:

Az egyenlőség jelölése C == -ben gyakori hibák forrása a hozzárendelés vezérlőkonstrukciókban való felhasználásának lehetősége miatt, de más nyelveken a probléma további korlátozások bevezetésével megoldható.

Például a PL/1 nyelvi kifejezésben :

A = B = C

a változóhoz a relációkifejezés logikai értékétА rendeljük hozzá . Az ilyen jelölések csökkentik az olvashatóságot , és ritkán használják. В = С

Szemantikai jellemzők

A feladat értelmezése korántsem mindig „intuitív” (az imperatív nyelvek programozói számára) az egyetlen igaz és lehetséges.

Az imperatív nyelvekben használt szintaxisból nem mindig lehet megérteni, hogyan valósul meg a hozzárendelési szemantika , hacsak nincs kifejezetten definiálva a nyelvben.

Például a Forth -ban a hozzárendelés előtt egy változó értékének és címének az adatverembe kell kerülnie, és ez jóval a tényleges hozzárendelés végrehajtása előtt megtehető.

Példa:

\ Az AAA változó definiálása és a következő sorban a 10-es érték hozzárendelése VÁLTOZÓ AAA 10 AAA!

Ugyanaz egy kicsit másképp:

tíz VÁLTOZÓ AAA AAA! Kétértelműség

Vegyünk egy példát:

X=2+1

Ez felfogható úgy, hogy "a 2+1 (azaz 3) számítás eredménye egy változóhoz van hozzárendelve X", vagy úgy, hogy "a 2+1 művelet hozzá van rendelve egy változóhoz X". Ha a nyelv statikusan van beírva , akkor nincs kétértelműség, azt a változó típusa X("egész" vagy "művelet") oldja fel. A Prologban a gépelés dinamikus , így két hozzárendelési művelet létezik: is - egyenértékű érték hozzárendelése és = - minta hozzárendelése. Ebben az esetben:

X értéke 2 + 1, X = 3 X=2+1, X=3

Az első sorozatot igaznak, a másodikat hamisnak ismeri el.

Szöveg

Amikor nagy méretű és összetett szerkezetű objektumokkal foglalkozik, sok nyelv az úgynevezett " referenciaszemantikát " használja. Ez azt jelenti, hogy a klasszikus értelemben vett hozzárendelés nem történik meg, de a célváltozó értékét a forrásváltozó értékével azonos helyen lévőnek tekintjük. Például ( Python ):

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

Ezt követően blesz értéke [1, 1000, 3] – egyszerűen azért, mert valójában az értéke az értéke a. Az ugyanarra az adatobjektumra vonatkozó hivatkozások számát számosságnak nevezzük, és magát az objektumot megölik (megsemmisítik vagy a szemétgyűjtőnek adják ), amikor a számosság eléri a nullát. Az alacsonyabb szintű programozási nyelvek (például C ) lehetővé teszik a programozó számára, hogy kifejezetten szabályozza, hogy mutatószemantikát vagy másolási szemantikát használjon-e.

Művelet helyettesítés

Sok nyelv lehetővé teszi a hozzárendelés jelentésének megváltoztatását akár a tulajdonságmechanizmuson keresztül, akár a hozzárendelés operátorának túlterhelésén keresztül . Csere szükséges lehet a hozzárendelt érték érvényességének ellenőrzéséhez vagy bármely más további művelethez. A hozzárendelési operátor túlterhelését gyakran használják „mély másolat” biztosítására, azaz a hivatkozások helyett értékek másolására, amelyeket alapértelmezés szerint sok nyelven másolnak.

Az ilyen mechanizmusok lehetővé teszik a munka kényelmét, így a programozó számára nincs különbség a beépített és a túlterhelt operátor használata között. Ugyanezen okból lehetségesek a problémák, mivel a túlterhelt operátor műveletei teljesen eltérhetnek az alapértelmezett operátor műveleteitől, és a függvényhívás nem nyilvánvaló, és könnyen összetéveszthető egy beépített művelettel.

Bővített tervek

Mivel a hozzárendelési operátort széles körben használják, a programozási nyelvek fejlesztői új konstrukciókat próbálnak kidolgozni, hogy egyszerűsítsék a tipikus műveletek írását (az úgynevezett " szintaktikai cukrot " hozzáadva a nyelvhez). Ezenkívül az alacsony szintű programozási nyelvekben a befogadási kritérium gyakran a hatékony végrehajtható kódokká való fordítás képessége. [3] A C nyelv különösen híres erről a tulajdonságáról .

Több célpont

Az egyszerű operátor egyik alternatívája az a képesség, hogy egy kifejezés értékét több objektumhoz is hozzárendeljük . Például a PL/1 -ben az operátor

ÖSSZESEN = 0

egyidejűleg nullát rendel a változókhoz SUMés TOTAL. Az Adában a hozzárendelés is utasítás, nem kifejezés, így a többszörös hozzárendelés jelölése a következő:

ÖSSZESEN: Egész szám := 0;

Egy hasonló hozzárendelés a Pythonban a következő szintaxissal rendelkezik:

összeg = összesen = 0

Ellentétben a PL/1-től, az Ada-tól és a Python-tól, ahol a többszörös hozzárendelés csak gyorsírásnak minősül, a C -ben, Lisp -ben és másokban ennek a szintaxisnak szigorú alapja van: a hozzárendelési operátor egyszerűen visszaadja a hozzárendelt értéket (lásd fent). Tehát az utolsó példa valójában:

összeg = (összesen = 0)

Egy ilyen sor működik C-ben (ha pontosvesszőt ad a végére), de Pythonban hibát okoz.

Párhuzamos hozzárendelés

Egyes nyelvek, például a Ruby és a Python támogatják a párhuzamos hozzárendelésnek nevezett kiterjesztett hozzárendelési szintaxist:

a , b = 1 , 11

Úgy gondolják, hogy egy ilyen hozzárendelés egyidejűleg és párhuzamosan történik , ami lehetővé teszi, hogy ezzel a konstrukcióval röviden végrehajtsuk két változó értékének cseréjét.

Írás párhuzamos hozzárendeléssel "Hagyományos" hozzárendelés: további változót és három műveletet igényel „Gazdaságos” hozzárendelés: nem igényel további változót, de három műveletet is tartalmaz Még "gazdaságosabb" hozzárendelés: nem igényel további változót, bitműveletekkel működik
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

Az utolsó előtti aritmetikai lehetőség nem biztonságos olyan programozási nyelveken vagy hardverplatformokon , amelyek ellenőrzik az aritmetikai túlcsordulást .

Ez utóbbi opció csak olyan típusokkal működik, amelyek támogatják a bitenkénti műveleteket (például a C#double fordító nem teszi lehetővé a változóértékek ilyen módon történő cseréjét).

Egyes nyelvek (például a PHP ) rendelkeznek konstrukciókkal a párhuzamos hozzárendelés szimulálására:

lista ( $a , $b ) = tömb ( $b , $a );

Feltételes célpontok

Egyes programozási nyelvek, például a C++ , lehetővé teszik a feltételes célokat a hozzárendelési utasításokban. Például a kifejezés:

( flag ? count1 : count2 ) = 0 ;

értéket rendel a 0változóhoz count1if , és if . flag==truecount2flag==false

A feltételes hozzárendelés egy másik változata ( Ruby ):

a ||= 10

Ez a konstrukció csak akkor rendel aértéket egy változóhoz, ha az érték még nincs hozzárendelve, vagy egyenlő a -val false.

Összetett állítások

Az összetett hozzárendelési operátor lehetővé teszi egy gyakran használt hozzárendelési forma rövidítését. Ezzel a módszerrel lerövidítheti egy olyan hozzárendelés jelölését, amely a célváltozót használja első operandusként a kifejezés jobb oldalán, például:

a = a + b

A C összetett hozzárendelési operátor szintaxisa a kívánt bináris operátor és a =. Például a következő bejegyzések egyenértékűek

sum += value; sum = sum + value;

Az összetett operátorokat támogató programozási nyelvek ( C++ , C# , Python , Java stb.) általában rendelkeznek verziókkal a legtöbb nyelv bináris operátorához+= ( , -=, &=stb.).

Unáris operátorok

A C család nyelveiben négy unáris (vagyis egy argumentumot véve) aritmetikai operátor létezik a számok eggyel növelésére és csökkentésére: két „ ” operátor és két „ ” operátor. Az operátorok írhatók az operandus elé (előtag) vagy utána (utótag vagy utótag). A prefix és postfix operátorok az értékelés sorrendjében különböznek. Az előtag operátorai eggyel módosítanak egy számot, és a módosított számot adják vissza. A Postfix operátorok egy számot tárolnak egy ideiglenes változóban, módosítják az eredeti számot, és visszaadják az ideiglenes változó értékét. ++--

Példa az operátor használatára : ++

Egy változó értékének növelése eggyel Egyenértékű jelölés
count ++; count = count + 1;

Bár nem tűnik feladatnak, de az. A fenti utasítás végrehajtásának eredménye ugyanaz, mint a hozzárendelés végrehajtásának eredménye.

A " " operátorokat növelő operátoroknak, a " " operátorokat pedig csökkentő operátoroknak nevezzük. Az operátorokat gyakran használják a C nyelvben mutatókkal és tömbindexekkel való foglalkozás során . ++--

Megvalósítás

A modern számítógépek működése abból áll, hogy a memóriából vagy az eszközből adatokat olvasnak be regiszterekbe, műveleteket hajtanak végre ezen az adatokon, és írnak a memóriába vagy eszközre. A fő művelet itt az adatátvitel (regiszterekből a memóriába, memóriából regiszterbe, regiszterből regiszterbe). Ennek megfelelően ezt közvetlenül a modern processzorok utasításai fejezik ki . Tehát az x86 architektúra esetében (az alábbi parancsok erre az architektúrára is vonatkoznak) ez egy művelet movés változatai különböző méretű adatok küldésére. A hozzárendelési műveletet (adatátvitel egyik memóriacellából a másikba) gyakorlatilag közvetlenül ez a parancs hajtja végre. Általánosságban elmondható, hogy a memóriában történő adatátvitel végrehajtásához két utasítás szükséges: egy memória-regiszter és egy regiszter-memória mozgás, de optimalizálásokkal az utasítások száma a legtöbb esetben csökkenthető.

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

Kódgenerálási példa ( GCC ), két
utasítás a hozzárendeléshez

Lásd még

Jegyzetek

  1. Niklaus Wirth . Jó ötletek: Nézzünk át a szemüvegen . Per. Szergej Kuznyecov (2006). Letöltve: 2006. április 23. Az eredetiből archiválva : 2011. szeptember 27..
  2. Niklaus Wirth. Jó ötletek, a szemüvegen keresztül . Letöltve: 2010. december 4. Az eredetiből archiválva : 2012. június 25.
  3. Optimalizálási célból sok műveletet hozzárendeléssel kombinálnak. A gyorsírási feladatoknak gyakran van megfelelője a gépi utasításokban. Tehát az eggyel növelést a gépi utasítás inc, az eggyel csökkentést - dec, az összeadást hozzárendeléssel - add, a kivonást a hozzárendeléssel - sub, a feltételes átviteli utasításokat - cmovastb cmovno.

Irodalom

  • Robert W. Sebesta. A programozási nyelvek alapfogalmai\u003d A programozási nyelvek fogalmai. - 5. kiadás - M .: Williams , 2001. - 672 p. - ISBN 0-201-75295-6 .
  • M. Ben-Ari. Programozási nyelvek. Gyakorlati összehasonlító elemzés. — M.: Mir, 2000. — 366 p. 71-74.
  • V. E. Wolfenhagen. Programozási nyelvek tervezése. Leírási módszerek. - M .: JSC Center YurInfoR, 2001. - 276 p. ISBN 5-89158-079-9 . 128-131.
  • E. A. Opaleva, V. P. Samoilenko. Programozási nyelvek és fordítási módszerek. - Szentpétervár: BHV-Petersburg, 2005. - 480 p. ISBN 5-94157-327-8 . 74-75.
  • T. Pratt, M. Zelkowitz. Programozási nyelvek: fejlesztés és megvalósítás. - 4. kiadás - Szentpétervár: Péter, 2002. - 688 p. ISBN 5-318-00189-0 , ISBN 0-13-027678-2 . 201-204.