Informatika2-2015/Eloadas 10 C-3 Mutatok

A MathWikiből
(Változatok közti eltérés)
Csirke (vitalap | szerkesztései)
(Új oldal, tartalma: „= Preprocesszor = A C programok fordítása két részből áll. Először lefut az úgynevezett "preprocesszor", és utána fut le a rendes fordító. A preprocesszor…”)
Újabb szerkesztés →

A lap 2015. április 22., 08:11-kori változata

Tartalomjegyzék

Preprocesszor

A C programok fordítása két részből áll. Először lefut az úgynevezett "preprocesszor", és utána fut le a rendes fordító. A preprocesszor olyan utasításokat kap, amiket a programon mint szövegen hajt végre, úgy, hogy még nem próbálja értelmezni hogy C-ben mit jelent az. Mindjárt meglátjuk hogy ennek milyen következményei vannak.

Persze általában nem kell tudnotok hogy egy fordító hogy működik belül, de mivel itt a preprocesszor eléggé mást és máshogy csinál mint a rendes fordítók, ezért külön tanuljuk azt ami hozzá tartozik.

A preprocesszornak a kettőskereszttel kezdődő sorok szólnak. Mivel ezek nem C parancsok egészen pontosan, más nevük van, preprocesszor direktíváknak hívjuk őket.

include

Az egyetlen példa amit láttunk eddig erre, az az "#include" parancs. Az #include az azt csinálja, hogy egy másik fájl teljes tartalmát beilleszti annak a sornak a helyére. tehát amikor azt írjuk, hogy

#include <stdio.h>

Akkor a fordító fog egy "stdio.h" nevű fájlt (ami a fordítón belül van), és annak a teljes tartalmát beilleszti ennek a sornak a helyére. Ez a fájl az, ami a különböző beépített függvények deklarációit tartalmazza, ezért használhatjuk őket, miután volt ilyen #include sor.

Ezzel lehet saját másik fájlokat is együtt felhasználni, akkor nem kacsacsőröket, hanem dupla idézőjeleket kell használni a fájlnévnél, így:

#include "masik_fajl.h"

Az a különbség a kettő között, hogy az idézőjellel megadott fájlokat először az aktuális könyvtárban keresi, míg a kacsacsőrrel megadottakat először a fordító könyvtárában keresi.

define

Vegyük ezt a korábbi példát:

// Dokumentaljuk is le, hogy max. 1000-el mukodik
int fun(int n) {
  if(n > 1000) {
    return -1;  // Ezzel a hibat jelezzuk
  }
  int tomb[1000];
  // A tenyleges szamolasok...
  // Amik a tomb-nek csak az elso n elemet hasznaljak
}

Itt az a probléma, hogy az "1000" mint limit, kétszer is le van írva. Ha meg akarjuk növelni a limitet 2000-re, könnyen elfelejthetjük, hogy két helyen is módosítani kell, és csak az egyiket írjuk át. Azonban, a szabvány szerint, nem használhatunk változót a tömb méretének megadására, ezért az sem működik, hogy eg változóba tároljuk el. Ehelyett a "#define" direktívát használhatjuk egy konstans meghatározására. Itt van ez jól megvalósítva:

#define TOMB_MAX_MERET 1000
 
// Dokumentaljuk is le, hogy max. 1000-el mukodik
int fun(int n) {
  if(n > TOMB_MAX_MERET) {
    return -1;  // Ezzel a hibat jelezzuk
  }
  int tomb[TOMB_MAX_MERET];
  // A tenyleges szamolasok...
  // Amik a tomb-nek csak az elso n elemet hasznaljak
}

Ezzel elértük hogy egy helyen elég módosítani a méretet. Azonban ezzel a #define-nal vigyázni kell. Ezt a preprocesszor csinálja, ami nem érti a C kódot, és annak különböző részeit, bárhol ahol azt a nevet látja amit megadtunk neki, oda behelyettesíti azt a másik betűsort amit megadtunk neki. Így pl. ha ezt írjuk:

#define a xxx
 
int alap(int u) {
  int az = 0;
  // stb...
}

Akkor ebben a kódban a preprocesszor a kis "a" betű minden előfordulását kicseréli, tehát "xxxlxxxp" nevű függvényt definiáltunk, és azon belül egy "xxxz" nevű változónk van. Ez még túlélhető lenne, de ha pl. az "i" betűt #define-olom, akkor már azt se írhatom le sikeresen hogy "int", így egész változókat nem tudok megadni.

Tehát a lényeg az, hogy olyan nevet adjak a #define-al megadott konstansnak, ami nem fordulhat elő máshol a kódban. Az általánosan elfogadott szokás az, hogy a #define-al megadott konstansoknak a neve csupa nagybetűből áll, ezt ajánlom követni.

Mutatók

A C-ben az ilyen mutable és immutable dolgok helyett van egy speciális külön típus, a mutató. Már az előző előadáson említettem a szintaxist, hogy hogy néz ki, a *-gal jelöljük. Tehát egy int típusú változóra mutató mutatót így definiálunk:

int *mutato;

Egyszerű változókra mutatók

A mutató típusú változók

Személyes eszközök