A C nyelvnek van egy speciális "tárolási osztályt" jelzõ kulcsszava, ez a typedef. Ha egy azonosító definíciója mellé ezt a tárolási osztályt adjuk meg, akkor az azt jelenti, hogy valójában nem hozunk létre új dolgot, hanem az adott azonosítót - mint egy szimbólumot - a megadott típus megnevezésére kívánjuk használni. Ez tehát kizárólag a fordítónak szól, a generált kódban ennek semmi nyoma nem lesz. Például:
typedef int bool; typedef float float_array[20]; typedef short *short_ptr;Az elsõ példa ugyanazt a funkciót látja el, mint az elõfeldolgozónál bemutatott szimbólum-definíció. A második létrehoz egy float_array nevû új típust, aminek segítségével lebegõpontos tömböket lehet definiálni. Tehát itt a megnevezett új típus a float_array, amelyet a float elemi típusból hozunk létre egy ún. típusmódosító operátor segítségével. Ez az operátor a [ ] tömbtípust képzõ operátor. Az utolsó példa egy mutatótípust - a rövid egészre mutató pointert - lát el azonosítóval. Ezt az új típust a * mutatótípust képzõ operátorral állítottuk elõ a short elemi típusból. Ez utóbbi két példában használt szerkezetre a késõbbiekben még visszatérünk. A fenti sorok leírása után szerpelhetnek a következõ alakú definíciók:
bool yesno; float_array t11; short_ptr shp;illetve alkalmazhatjuk a következõ függvénydeklarációt:
extern bool ext_fv(short_ptr, bool, float_array);A C-ben természetesen nem csak tárterületfoglaló tárolási egységekre vonatkozó típusokat hozhatunk létre, hanem kódgeneráló tárolási egységek típusait is definálhatjuk, azaz különféle függvénytípusokat adhatunk meg. A fentiekhez hasonlóan, ez a típusdeklaráció is olyan, mintha egy typedef "tárolási osztályú" függvényt deklarálnánk. Például a
typedef double dbl_fv(double, int);deklaráció értelmében az új típus neve dbl_fv. Ezt a típust a double elemi típusból hoztuk létre a ( ) függvénytípust képzõ operátorral. A fenti példa szerinti dbl_fv olyan duplapontosságú valós értéket visszaadó függvény típusának az azonosítója, amely paraméterként egy double és egy int értéket vár. Az így létrehozott új típusazonosítót felhasználva írhatjuk, hogy
dbl_fv power;ami teljesen ekvivalens egy modern stílusú függvénydeklarációval. Deklarálunk tehát egy power azonosítójú tárolási egységet, amelynek a típusa dbl_fv. Bár formailag úgy néz ki, hogy ez nem pusztán deklaráció, hanem egy komplett definició, ne feledjük, hogy a kódegeneráló tárolási egységek esetében a teljes definicióhoz szükség van a függvény törzsére is!
A függvénydeklarációk fenti módját nem javasoljuk, hiszen rejtve marad az, hogy power valójában nem egy változó, hanem egy adott fajta függvény, mindazonáltal a dbl_fv típus deklarálása nem haszontalan. Segítségével könnyen deklarálhatunk függvényre mutató pointereket:
dbl_fv *fv_mutato;A függvénekre mutató pointerek használatával a 1.9.8-as részben foglalkozunk részletesebben.
Az egyszerû ökölszabályon - azaz a typedef "tárolási osztályú" deklarációk megadásán - túlmenõen, az alábbiak szerint foglalhatjuk össze precízen egy új típus definiálásának szabályait.
Új típust mindig valamilyen már meglévõ
típusból (elemi típusból, struktúrákból,
vagy typedef-fel már korábban definiált típusból)
hozhatunk létre úgy, hogy megnevezzük az új típust,
és erre az új típusazonosítóra alkalmazzuk
az egyes típusmódosító operátorokat
(( ), [ ], *). Természetesen, ha egy
bonyolultabb típust akarunk deklarálni (például
egészekre mutató pointert visszaadó függvények
tömbjét), figyelembe kell vennünk a típusmódosító
operátorok precedenciáját, és ennek megfelelõen
kell a típusdefinició során zárójeleznünk.
A típusmódosító operátorok közül
a * prefix operátor (a módosítandó
típus elõtt áll), míg a ( ) és
a [ ] operátorok postfix operátorok (a módosítandó
típus után állnak). Az típusmódosító
operátorokra vonatkozó ismereteket a 1.4
táblázatban foglaltuk össze.
Operátor | Megnevezés | Jelleg |
( ) | függvénytípust képzõ operátor | postfix |
[ ] | tömbtípust képzõ operátor | postfix |
* | mutatótípust képzõ operátor | prefix |
Típusdefiniálásra vonatkozó példákat találhatunk még a 1.9.1-es pontnál. A 1.12.2-es pontban a típusdefiniálással kapcsolatban további részletkérdésekre térünk ki.
Megjegyzendõ, hogy a típusmódosító operátorok a szó szorosan vett értelmében nem operátorok, hiszen nem a C programunk futása során történõ tényleges mûveletvégzésre adnak utasítást, hanem csak a fordító program mûködését befolyásolják: arról adnak információt, hogy egy adott típust hogy, s mint kell kezelni a fordítás hátralévõ részében.