Változó (számítástechnika)

A Wikipédiából, a szabad enciklopédiából

A programozásban a változó egy absztrakt tárolóhely, amelyet egy szimbolikus névvel társítanak, amelyben bizonyos ismert vagy ismeretlen mennyiségű adat van tárolva. Ezt értéknek nevezzük. Egyszerűbben fogalmazva, a változó egy elnevezett tároló azonos típusú adatok vagy bitkészletek számára (mint például egész szám, lebegőpontos szám, karakterlánc stb.). A változó társítva, azonosítva van egy memóriacímmel. A változó nevével a tárolt értékre, valamint magára a változóra is hivatkozunk, ez a kontextustól függ. A név és a tartalom szétválasztása lehetővé teszi, hogy a név az általa képviselt pontos információtól függetlenül használható legyen. A forráskódban lévő azonosítót futási időben köti az értékhez, így a változó értéke a program végrehajtása során változhat.[1][2][3][4]

A programozásban előforduló változók nem feltétlenül felelnek meg közvetlenül a matematikai változók fogalmának. Ez utóbbi absztrakt, nem utal fizikai objektumra, például tárolóhelyre. A változó értéke nem feltétlenül része egy egyenletnek vagy képletnek úgy, mint a matematikában. Programozásban a változókat gyakran hosszú nevekkel látják el, hogy viszonylag jól leírják a felhasználásukat, míg a matematikában a változók gyakran tömör, egy vagy két karakteres neveket kapnak, hogy rövid legyen az átírás és manipuláció.

Egy változó tárolási helyére többféle azonosítóval lehet hivatkozni, amit aliasing-nak nevezünk. Ha az egyik azonosítóval értéket rendelünk a változóhoz, akkor megváltozik a többi azonosítón keresztül elérhető érték.

A fordítók ki kell cseréljék a változók szimbolikus neveit a tényleges adatok helyével. Habár a változó neve, típusa és helye gyakran állandó marad, az adatai, amelyek a helyen tárolódnak, megváltozhatnak a program végrehajtása során.

Műveletek a változón[szerkesztés]

Az imperatív programozási nyelvekben az értékek általában bármikor elérhetők vagy megváltoztathatók. A tisztán funkcionális és logikai nyelvekben a változók kifejezésekhez vannak kötve, és élettartamuk során egyetlen értéket tartanak meg a hivatkozási átlátszóság követelményei miatt. Az imperatív nyelvekben hasonló viselkedést mutatnak a konstansok, amelyeket gyakran állítják szembe a változókkal.

A programozási nyelv típusrendszerétől függően a változók csak egy adott adattípust képesek tárolni (például egész vagy karakterlánc). Más esetben az adattípus csak az aktuális értékkel lehet összekapcsolva, ami lehetővé teszi, hogy egyetlen változó bármit tároljon, ami a programozási nyelv által támogatott. A változók az értékek tárolására szolgáló tárolók.

Változók és hatáskörük:

  • Automatikus változók: A függvény minden helyi változója csak a függvény meghívásakor jön létre, és eltűnik, amikor kilép a függvényből. Az ilyen változókat automatikus változóknak nevezzük.
  • Külső változók: Ezek olyan változók, amelyek egy függvényen kívül esnek, és név szerint bármely függvény számára elérhetők. Ezek a változók állandóan léteznek; Ahelyett, hogy a függvények meghívása és kilépése során megjelennének és eltűnnének, megőrzik értékeiket az őket beállító függvények visszatérése után is.

Változóra hivatkozó azonosítók[szerkesztés]

Egy változóra hivatkozó azonosító segítségével hozzáférhetünk a változóhoz, hogy kiolvassuk, megváltoztassuk az értékét, vagy akár más attribútumait is szerkeszthetjük. Ilyen például a hozzáférési engedély, zár, és a szemaf stb.

További példaként, egy változóra hivatkozhat a „total_count” azonosító, és a változó tartalmazhatja az 1956 számot. Ha ugyanarra a változóra hivatkozik az „r” azonosító is, és ha ezzel az „r” azonosítóval megváltoztatjuk a változó értékét 2009-re, akkor az „total_count” azonosítóval történő kiolvasás 2009-et ad eredményül, és nem 1956-ot.

Ha egy változóra csak egyetlen azonosító hivatkozik, akkor ezt az azonosítót egyszerűen a változó nevének nevezhetjük; különben a változó egyik neveként beszélhetünk róla. Például az előző példában a „total_count” azonosító a kérdéses változó neve, a „r” pedig egy másik név ugyanarra a változóra.

Hatáskör és élettartam[szerkesztés]

A változó hatásköre (angolul scope) leírja, hogy a program mely részén lehet használni a változót, míg a változó élettartama azt írja le, hogy a program végrehajtása során mikor van a változónak értéke. A változó hatásköre befolyásolja annak élettartamát. A változó hatásköre valójában a változó nevének tulajdonsága, az élettartam pedig a változó tárolási helyének tulajdonsága. Ezeket nem szabad összetéveszteni a környezettel, amely a program tulajdonsága, és a program szövegében vagy végrehajtásában pontonként változik. Továbbá, az objektum élettartama egybeeshet a változó élettartamával, de sok esetben nincs kötve hozzá.

A hatáskörnek fontos része van a változó nevének feloldásában. A legtöbb nyelv külön határozza meg a hatáskört minden változóhoz (valamint más nevű entitásokhoz is), amely egy adott programon belül eltérhet. A változó hatásköre a programkódnak az a része, ahol a változót el tudjuk érni, és ahol „láthatónak” mondhatjuk. A hatáskörbe való belépés általában a változó élettartamának a kezdetét jelzi (amikor értelmezhetővé válik), míg a hatáskörből történő kilépés a változó élettartamának végét jelzi (amikor már nem értelmezhető). Például, egy „lexikális hatáskörű” változó csak egy bizonyos függvény/alprogramban, máshogy fogalmazva, egy blokkban értelmezhető (függvényhatókör vagy blokkhatókör alapján); ez a statikus feloldás, amely elemzési időben[note 1] vagy fordítási időben történik. Másrészt, egy dinamikus hatáskörű változó futásidőben oldódik fel, egy globális kötési verem alapján, amely az adott vezérlőfolyamtól függ. Azokat a változókat, amelyek csak bizonyos függvényekben érhetők el, lokális változóknak nevezzük. Egy globális változó, vagy végtelen hatáskörű változó, bármikor hivatkozható a program bármely pontján.

Az élettartam (angolul extent) egy változó futási időben (dinamikusan) működő tulajdonsága. A futási időben, a változó minden egyes kötésének más-más élettartama lehet. A kötés mértéke a program végrehajtási idejének azon része, amely alatt a változó továbbra is ugyanarra az értékre vagy memóriahelyre hivatkozik. Egy futó program többször léphet be és ki egy adott élettartamból, például zárójelek esetében.

Hacsak a programozási nyelv nem támogatja az automatikus memóriakezelést, egy változó, amelynek az élettartama meghaladja a hatóköreit, memóriaszivárgást eredményezhet. Ez azt jelenti, hogy a változóhoz rendelt memóriaterület sosem szabadul fel, mivel a változó, amelyet a felszabadítási célokra használnánk, már nem elérhető. Vannak olyan esetek amikor elfogadható, hogy egy változó kötése túlnyúlik a hatáskörein, például a Lisp zárójeleiben és a C statikus helyi változóiban; amikor a végrehajtás visszakerül a változó hatáskörébe, a változó ismét használhatóvá válik. Azt a változót, amelynek hatásköre az élettartama előtt kezdődik, „inicializálatlannak” mondják, és ha hozzáférünk, akkor gyakran meghatározatlan, tetszőleges értékkel rendelkezik, mivel még nem adtunk neki konkrét értéket. Az a változó, amelynek élettartama a hatóköre előtt véget ér, „lógó” mutatóvá válhat (dangling pointer), és újra inicializálatlannak tekinthető, mivel az értéke megsemmisült. Az előző két esetben leírt változókat úgy is leírhatjuk, hogy nincsenek hatáskörükön belül vagy kötésük feloldatlan. Sok nyelvben hiba, ha egy változó értékét a hatáskörein kívül használjuk. Más nyelvekben azonban kiszámíthatatlan eredményt adhat. Egy ilyen változónak azonban adhatunk új értéket, amely új élettartamot ad neki.

A helytakarékosság érdekében a változók számára szükséges memóriaterület csak akkor kerül lefoglalásra, amikor a változó első alkalommal használatba kerül, és felszabadul, amikor már nincs rá szükség. Egy változóra akkor van csak szükség, amikor a hatáskörén belül vagyunk, így az élettartamuk akkor kezdődik, amikor a hatáskörbe kerülnek, ezzel helyet adva a nem használt változóknak. Az ilyen helypazarlás elkerülése érdekében a fordítók gyakran figyelmeztetik a programozókat, ha egy változó deklarált, de nem használt.

Jó programozási gyakorlatnak tartják azt, ha a változók köre a lehető legszűkebbre van szabva, így a különböző programrészek nem tudják véletlenül sem egymás változóit módosítani. Ezzel megakadályozza a távoli tevékenységet is. Gyakran alkalmazott technikák közé tartozik a program különböző részeinek eltérő névterekben történő használata, vagy az egyedi változók „priváttá” tétele dinamikus vagy lexikális változó hatáskörével.

Sok programozási nyelv használ egy fenntartott értéket (általában null vagy nil néven), amely az érvénytelen vagy inicializálatlan változókat jelzi..

Típus[szerkesztés]

A statikus típusú nyelvekben, például a Go-ban vagy az ML-ben, egy változóhoz típus is tartozik, ami azt jelenti, hogy csak bizonyos típusú értékek tárolhatóak benne. Például egy „integer” (egész szám) típusú változóba nem lehet szöveges értéket tárolni.

Dinamikus típusú nyelvekben, például a Pythonban, a változó típusa az értékéből következtethető, és az értékének megfelelően változhat. A Common Lispben mindkét helyzet egyszerre áll fenn: a változóhoz típus van rendelve (ha nem lett deklarálva, akkor az T típusra van feltételezve, az univerzális szupertípusra), amely a fordítási időben van jelen. Az értékeknek vannak típusai is, amelyek futás közben ellenőrizhetők és lekérdezhetők.

A változók típusának meghatározása lehetővé teszi a fordítási időben történő polimorfizmust. Ez azonban eltér az objektumorientált függvényhívásokban használt polimorfizmustól (amit C++-ban virtuális függvényeknek neveznek), amely a hívás feloldását az értéktípus alapján oldja meg, nem pedig azon szupertípusok alapján, amelyeket a változó elfogadhat.

A változók gyakran egyszerű adatokat tárolnak, mint például egész számokat és karakterláncokat, de néhány programozási nyelv lehetővé teszi, hogy a változók más adattípusok értékeit is tárolják. Ilyen nyelvek lehetővé tehetik a függvények parametrikus polimorfizmusát is. Ezek a függvények úgy működnek, mint változók: képesek több típusú adat tárolására. Például egy hossz függvény meghatározhatja a lista hosszát. Az ilyen függvény azonban parametrikus polimorf is lehet ha típusváltozót tartalmaz a típusdeklarációjában, mivel a lista elemeinek száma nem függ az elemek típusától.

Paraméterek[szerkesztés]

A függvények formális paramétereit (vagy formális argumentumait) változóknak is nevezik. Például ebben a Python kódszegmensben,

>>> def addtwo(x):
...     return x + 2
...
>>> addtwo(5)
7

az x nevű változó egy paraméter, mert a függvény meghívásakor kap értéket. Az 5 egész szám, az az argumentum, amely megadja x értékét. A legtöbb nyelvben a függvényparaméterek helyi hatáskörrel rendelkeznek. Erre az x változóra csak az addtwo függvényen belül lehet hivatkozni (természetesen más függvényeknek is lehetnek x nevű változói).

Memóriakiosztás[szerkesztés]

A változók kiosztása és értékeik reprezentációja széles körben változik mind a programozási nyelvek között, mind az adott nyelv implementációi között. Számos nyelvi implementáció foglal helyet a helyi változóknak, amelyek kiterjedése egyetlen függvényhívásig tart a hívási veremben (call stack), és amelyek memóriáját a rendszer automatikusan felszabadítja, amikor a függvény visszatér. Általánosságban elmondható, hogy a névkötés (name binding) során a változó neve egy meghatározott memóriaterület (összefüggő sorozat) címéhez van kötve, és a változón végzett műveletek a memóriablokk manipulálását jelentik. A hivatkozás gyakoribb olyan változóknál, amelyek értékei nagyok vagy ismeretlenek a kód fordítási idejekor. Az ilyen változók az érték helyett az érték helyére hivatkoznak, amelyet a heap memóriatartalomból foglalnak le.

A kötött változók rendelkeznek értékkel. Az érték azonban egy absztrakció, egy gondolat; az implementáció során az értéket egy adatobjektum képviseli, amely valahol a számítógép memóriájában van tárolva. A programnak vagy a futási környezetnek memóriát kell fenntartania minden adatobjektum számára, és mivel a memória véges, biztosítania kell, hogy ez a memória újra felhasználhatóvá váljon, amikor az objektum már nem szükséges egy változó értékének reprezentálásához.

A heapből lefoglalt objektumokat vissza kell szerezni – különösen akkor, ha az objektumokra már nincs szükség. Szemétgyűjtővel rendelkező (garbage-collected) nyelvben (például C#, Java, Python, Golang és Lisp) a futási környezet automatikusan visszanyeri az objektumokat, amikor a meglévő változók már nem tudnak hivatkozni rájuk. Azoknak a nyelveknek, amelyek nem rendelkeznek szemétgyűjtővel, például C-ben, magának a programnak (és a programozónak) kell foglalnia a memóriát, majd később fel kell szabadítania, hogy visszanyerje a memóriát. Ha ezt nem tesszük meg, akkor memóriaszivárgás alakul ki, a heap kimerül a program futása során, ami a rendelkezésre álló memória elfogyásához vezet, és végül a program hibával leállhat.

Ha egy változó dinamikusan létrehozott adatstruktúrára hivatkozik, akkor az adatstruktúra egyes elemei csak közvetve érhetők el a változón keresztül. Ilyen helyzetekben a szemétgyűjtőnek kezelnie kell azt az esetet, amikor csak részlegesen kell visszaszerezni a változóhoz tartozó memóriát.

Elnevezési szabályok[szerkesztés]

A programozási változók és konstansok általában több karakterből álló neveket kapnak, ellentétben a matematikai megfelelőikkel, például COST vagy total. Egy karakterből álló neveket általában csak segédváltozókhoz használnak, például az i, j, k tömbindex változókhoz.

Egyes elnevezési konvenciók nyelvi szinten érvényesülnek, a nyelv szintaxisának részeként, amely magában foglalja az érvényes azonosítók formátumát. Majdnem minden nyelvre igaz, hogy a változónév nem kezdődhet számmal (0-9) és nem tartalmazhat szóköz karaktereket. Az, hogy a változónévben engedélyezettek-e az írásjelek, nyelvről nyelvre változik; sok nyelv csak az alulvonást („_”) engedélyezi a változónévben, és minden más írásjelet tilt. Egyes programozási nyelvekben jeleket (szimbólumokat vagy írásjeleket) rögzítenek a változóazonosítókhoz, hogy jelezzék a változó adattípusát vagy hatáskörét.

A változónév nagybetű- és kisbetű-érzékenysége (case-sensitivity) is eltérő lehet nyelvenként, néhány közülük megköveteli, hogy bizonyos entitások nevei milyen módon tartalmazzanak nagy- és kisbetűket.[note 2] A legtöbb modern nyelv megkülönbözteti a kis- és nagybetűket, míg néhány régebbi nem. Néhány nyelv fenntart bizonyos változónév formákat saját belső használatára; sok nyelvben a két aláhúzásjellel („__”) kezdődő nevek gyakran ebbe a kategóriába tartoznak.

Azonban a változók elnevezése nagyrészt stílus kérdése, a nyelv által előírt alapvető korlátozásokon túl. Gépi kód szinten nincsenek változónevek, így a választott pontos nevek nem számítanak a számítógép számára. A változókat a neveik azonosítják, minden más szempontból pedig csak eszköz a programozók számára, hogy könnyebbé tegyék a programok írását és megértését. A rosszul megválasztott változónév nehezebbé teheti a kód áttekintését, mint például a nem leíró jellegű nevek, ezért általában a tisztán értelmezhető nevek használata javasolt.[5][6]

A programozók gyakran létrehoznak és betartják a kódstílus-irányelveket, amelyek útmutatást adnak a változók elnevezéséhez, vagy pontos elnevezési sémát írnak elő. A rövidebb neveket gyorsabban lehet begépelni, de kevésbé leíró jellegűek; A hosszabb nevek gyakran megkönnyítik a programok olvashatóságát és a változók létrehozási céljának megértését. A változónevek szélsőséges bőbeszédűsége azonban kevésbé érthető kódhoz is vezethet.

Változótípusok (élettartam alapján)[szerkesztés]

A változók élettartamuk alapján több típusba sorolhatók. Ezek a: statikus, veremalapú, explicit heap-alapú és implicit heap-alapú változók.

A statikus változó, amit globális változóként is ismerünk, a program végrehajtása előtt egy memóriacellához rendelődik, és ugyanabban a cellában marad egészen a végrehajtás befejezéséig. Tipikus példa erre a statikus változók használata a C és C++ nyelvekben.

A veremalapú változók, amiket lokális változóknak is nevezünk, a deklarációs utasítás végrehajtásakor jönnek létre, és az eljárás visszatérésekor szűnnek meg. Például a C nyelvben a helyi változók a függvényekben, míg a Java nyelvben a metódusokban találhatók.

Az explicit heap-alapú változók névtelen (absztrakt) memóriacellák, amelyeket a programozó által meghatározott explicit futásidejű utasításokkal foglalnak le és szabadítanak fel. Például a C++ nyelvben a dinamikus objektumokat az „új” és „törlés” utasításokkal hozzák létre és szüntetik meg, míg a Java nyelvben minden objektum ilyen módon kezelhető.

Az implicit heap-alapú változók csak akkor kapcsolódnak a heaphez, amikor értéket rendelnek hozzájuk. Az allokáció és a felszabadítás akkor történik, amikor az értéket újra hozzárendelik a változóhoz. Ennek eredményeként az implicit heap-alapú változók a legnagyobb rugalmasságot biztosítják. Ilyen típusú változók például a JavaScript, PHP és APL nyelvekben találhatók.

Megjegyzések[szerkesztés]

  1. parse-time – forráskód elemzési fázisa a programfordítás alatt
  2. Például a Haskell megköveteli, hogy a típusok neve nagybetűvel kezdődjön.

Hivatkozások[szerkesztés]

  1. Compilers: Principles, Techniques, and Tools, pp. 26–28
  2. Knuth, Donald. The Art of Computer Programming, 3rd, Reading, Massachusetts: Addison-Wesley, 3–4. o. (1997. április 26.). ISBN 0-201-89683-4 
  3. Programming with variables. Khan Academy . (Hozzáférés: 2020. március 23.)
  4. Scratch for Budding Coders. Harvard. [2020. március 23-i dátummal az eredetiből archiválva]. (Hozzáférés: 2020. március 23.)
  5. How Not To Pick Variables, Retrieved July 11, 2012, (accessdate = 2023-05-27)
  6. Edsger Dijkstra, To hell with "meaningful identifiers"!, <http://www.cs.utexas.edu/users/EWD/transcriptions/EWD10xx/EWD1044.html>

Fordítás[szerkesztés]

Ez a szócikk részben vagy egészben a Variable (computer science) című angol Wikipédia-szócikk ezen változatának fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.

Kapcsolódó szócikkek[szerkesztés]