Dalsi zahada v C -> Prevod long int na string

Jan Waclawek konfera na efton.sk
Úterý Červenec 26 00:12:53 CEST 2011


> Neviem, ktora cast normy o tom pojednava, resp. tento zapis pripusta (a 
> nemienim to sialenstvo teraz studovat).

Predostieram, ze C z hlbky duse nenavidim.

Jedna sa o kombinaciu dvoch najodpornejsich hackov v C, jednym su tzv. string literals, ktorym sa imituju retazce (ktore v C v skutocnosti implementovane nie su), a druhym je ta hranata zatvorka, ktorou sa imituju polia (ktore v C tiez v skutocnosti implementovanie nie su).

String literals (formalne 6.4.5, ale v skutocnosti treba precitat vsetko kde sa toto slovne spojenie vyskytuje) je skupina znakov uzavreta v uvodzovkach, ktore sa prelozia ako bezmenne pole char inicializovane na jednotlive znaky medzi uvodzovkami plus nulovy znak na koniec. Ak sa to pouzije ako vyraz (ktory moze byt sucastou ineho vyrazu, napr. priradenia), predstavuje to teda ukazovatel na prvy znak takehoto pola. V 6.4.5#6 je vyslovne uvedene, ze taketo polia sa mozu "znovupouzit" a ze pokus o ich prepisanie ma nedefinovane nasledky. Az na tu poslednu vetu je teda napriklad zapis 
char * a = "abcd"; 
semanticky ekvivalentny zapisu
char anonymous[] = {'a', 'b', 'c', 'd', '\0');
a = &anonymous[0];
(pricom symbol anonymous je samozrejme neexistujuci, v programe nedostupny).

Hranate zatvorky (6.5.2.1, "array subscripting") je postfixovy operator, ktorym sa imituje pristup k prvkom pola prostrednictvom ukazovatelovej aritmetiky. Jednoducho sa scitaju hodnoty vyrazov pred a v hranatej zatvorke (s dodrzanim pravidiel ukazovatelovej aritmetiky, t.j. ze sa "scitava" v nasobkoch velkosti typu na ktory sa ukazuje - poziadavkou na tento typ vyrazu je, ze je prave jeden z "ucastnikov" typu ukazovatel) a to da vysledny ukazovatel, ktory sa nasledne dereferencuje. Norma doslovne hovori, ze E1[E2] is identical to (*((E1)+(E2))). 

Takze v nasom priklade najprv vznikne z retazca pole znakov (pricom sa vyplytva jedno miesto na nulovy znak, ktory nikdy nepouzijeme, ak len radix nebude >16, kedy vsak aj tak vysledok bude blbost), vo vyraze sa retazec nahradi ukazovatelom na prvy znak tohoto pola znakov, index v hranatej zatvorke sa pricita k tomuto ukazovatelu, a vysledok sa dereferencuje.

Nasledkom tejto perverznej konstrukcie je napriklad aj to, ze uvedeny priklad
"0123456789ABCDEF"[n % radix]
sa da ekvivalentne zapisat aj ako
(n % radix)["0123456789ABCDEF"]

O obludnosti, ktorou je postfixovy ++ sa na tomto mieste kvoli zachovaniu dusevneho zdravia radsej nebudem zmienovat... :-)

wek


Další informace o konferenci Hw-list