ketvirtadienis, vasario 01, 2007

C/C++ tipų deklaracijos

Neperseniausiai perskaičiau C istorijos straipsnį. Buvo labai įdomu sužinoti, kodėl priimti vieni ar kiti sintaksės, arba pačios kalbos sprendimai. Vienas iš tokių -- tipų deklaravimas C/C++ kalbose.

Vardai (kintamieji, funkcijos) definuojami tokia pat išraiška, kaip kad tie patys vardai yra resolvinami į reikšmes, be abejo atsižvelgiant į operatorių prioritetus. Pamenu anksčiau buvo sušmėžavus tokia mintis, bet kažkaip daugiau apie tai nemasčiau, tad realiai šitą faktą suvokiau tik perskaitęs minėtą straipsnį. Taigi pavyzdžiui turint pointerį į int'ą pi, reikšmės, į kurią šis rodo, paėmimas, atrodo taip: *pi. Tai yra operatoriaus* įvykdymas po jo einančiai išraiškai. O tokio pointerio definicija atrodo šitaip int* pi. Tai paaiškinama taip - šis užrašas parodo, kad int'ą mes gausime, jei pritaikysime operatorių * pi reikšmei. Štai keletas pavyzdžių:

void (*pointer_to_fun)( int );

Pasako, kad pritaikę operatorių * vardui pointer_to_fun, mes gausime "funkciją" void (int), t.y. kažką, kam reikia taikyti operatorių () ir po to gauti void. Turėtų b9ti aišku, kodėl kodas:

void* not_so_pointer_to_fun( int );

pointerio nebeaprašo. Operatorius () turi prioritetą prieš operatorių * ir "funkcijos kvietimas" turės būti prieš pointerio resolvinimą. Taigi išraiška rodo, kad "iškvietus" vardą not_so_pointer_to_fun (kuris reikalauja argumento int), ir tik po to pritaikius operatorių *, mes gausime void. Toliau:

int arr[];

pritaikę operatorių [] vardui arr gausim int'ą.

int* (*arr1)[];

pritaikę op* vardui arr1, gausime masyvą, šiam pritaikę op[] gausime pointerį į int ir finale, po dar vieno operatoriaus*, gausime int. Taigi, tipas arr1 aprašo pointerį į masyvą iš pointerių į int'us.

Beje, atrodo, C++ reference deklaracija (&) į šią sistemą kažkaip netelpa.

Kaip rašė pats D. Ritchie - egzistuoja daug nusiskundimų, kad tipų aprašymas C kalboje yra labai sudėtingas, ypač kai tai liečia funkcijas ir/arba masyvus. Į ką jis atsako - taip, jis yra sudėtingas, bet tik tam ir dėl to, kad sudėtingos yra pačios išraiškos. Pilnai sutinku.

Jei dar neatsibodo - o kas yra čia?

void* (*(*a)[])(int*&);

5 komentarai:

ReJ rašė...
Autorius pašalino šį komentarą.
ReJ rašė...

int moo = 0;
int const boo = 0xc0da;
int const foo = 0x31337;
int* zoo = &boo;

// somewhat unsafe code
while(zoo == &boo)
{
memcpy((*((*a)[moo++]))(zoo), &foo, sizeof(int));
}

ReJ rašė...

2nd try. Dabar jau ir compiliuojasi ;)

int moo = 0;
int boo = 0xc0da;
int const foo = 0x31337;
int* zoo = &boo;

// somewhat unsafe code
while(zoo == &boo)
{
memcpy((*((*a)[moo++]))(zoo), &foo, sizeof(int));
}

vornoff rašė...

ok. easy: pointeris į masyvą iš pointerių į funkciją, apsiargumentavusią ref-ptr-į-int ir gražinančią void-ptr. apskritai, šiaip c/c++ "atspėk tipą" žaidimai yra pasenę, nusibodė ir niekam neįdomūs :) pats nesuprantu, kodėl aš tokia linkme postą pakreipiau.. imho, dabar įdomesnis žaidimas (jei jau c++) yra su "metaprogramavimais", pvz. čekout xpressive, boost.proto arba boost.accumulators bibliotekų sorsus. imho tam tikros jų dalys (ypač pastarųjų) atkeliavusios iš parallel-evil-abstract-ish reality. pagarba, aišku, bet įdomu link ko tai prives ir kuom tai baigsis

vornoff rašė...

aij, dar pamiršau pasakyt, kad šis užrašymas "(*((*a)[moo++]))(zoo)" (kuris iš esmės niekuom nesiskiria nuo a deklaracijos) labai padėjo žodžiais išreikšt tipą.. keep up the good work :)