PDA

Prikaži potpunu verziju : Funkcije u windows.h biblioeci...


ozzytheking
30.3.2012, 14:33
Neke windows.h (wincon.h) funkcije imaju za argument pokazivac na promenljivu u koju ce biti smesten broj koji obicno predstavlja broj uspesno obavljenih operacija unutar funkcije i vrlo cesto je potpuno beskorisno znati broj uspesnih <cega god>. Primer. Funkcija za stampanje karaktera na nekoj poziciji na konzoli izgleda ovako - FillConsoleOutputCharacter(Izlaz, 'A', 1, (COORD){1, 1}, &BESKORISNO_*****E) i u promenljivu BESKORISNO_*****E ce biti smesten broj uspesno odstampanih karaktera. E sad, posto mi je trulo da imam promenljivu BESKORISNO_*****E, a ni za sta mi ne treba, uz malo eksperimentisanja dodjoh do zakljucka da FillConsoleOutputCharacter(Izlaz, 'A', 1, (COORD){1, 1}, &(DWORD <tj. unsigned long>){0}) radi identicno. Ono sto mi nije jasno je kako &(DWORD){0} radi.
Skoro sam provalio da kada prosledjujem strukturu kao argument funkciji ne moram prvo da pravim novu promenljivu vec mogu "na licu mesta" da napravim i prosledim strukturu (ovo (COORD){1, 1}). Moje shvatanje ovog je da to radi kao sa primitivnim promenljivama npr. int a = 5; funkcija(a + 1); ali onda ne kapiram zasto &(DWORD){0} radi jer po nekoj logici, taj argument nije fizicka/definisana promenljiva u koju ce (u slucaju funkcije FillConsoleOutputCharacter) biti smesten broj uspesno odstampanih karaktera, vec samo "na licu mesta zbuckan i prosledjen broj tj. njegova adresa". Gde gresim?
Malo sam ga zakomplikovao. :D

Geomaster
7.4.2012, 22:43
Jeste da je matora tema, ali odgovoriću svejedno, ako još nisi naleteo na odgovor ili ako nekog drugog bude interesovalo.
Funkcije ne samo u Windows API-ju već u gomili drugih API-ja imaju ovakav način da se vrate neki rezultati. Međutim, naravno, programeri koji su dizajnirali ovaj API su predvideli da ti podaci koji se vraćaju neće uvek biti korisni, odnosno nekog korisnika ne bi uvek zanimali. Iz tog razloga je uglavnom nepisano pravilo da se, ako se u nekom parametru koji bi trebao da služi za izlaz, prosledi nulti pokazivač (odnosno &(DWORD(0) iliti NULL, a u novom C++11 nullptr) tada se ti podaci ni ne vraćaju. NULL je uvek zagarantovan da ne pokazuje na validnu memorijsku lokaciju pa je idealan kandidat za takav placeholder.
Dakle, ako funkciju pozoveš kao FillConsoleOutputCharacter(Izlaz, 'A', 1, (COORD){1, 1}, NULL), tada se ovaj parametar gde je NULL neće ni uzimati u obzir. Da je funkcija stvarno pokušala da upiše na memorijsku adresu koju si joj prosledio, dogodio bi se grozan segfault.

Belphegor
7.4.2012, 23:28
Ta multifunkcionalnost ume pomalo da nervira. Evo pogledaj recimo ovu funkciju CreateProcess (http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspx) . :D

ozzytheking
8.4.2012, 15:10
@Geomaster: Bas je fora u tome da NULL ne sme da se prosledi. I ja sam se vodio tom logikom da ako prosledim NULL kao argument da funkcija nece upisivati nista u lokaciju zadatu argumentom (kao npr time(NULL)), ali to ne radi, odnosno radi kad se program pokrene normalno, ali prilikom debagovanja se javlja SEGF. I to nije slucaj samo sa tom funkcijom, nego sa svim Windows funkcijama (barem onim sa kojima sam ja radio), neke cak ne uspeju ni da urade ono za sta su zaduzene pre nego sto se javi SEGF (konkretno ReadConsoleInput()).

Sad kad pogledam ovo sto je Belphegor postavio, izgleda da ovo "opt" znaci da moze da se prosledi i NULL, ali nijedna od ovih funkcija koje ja koristim nema "opt" kao osobinu/stagod argumenta.

Belphegor
8.4.2012, 15:59
'opt' predstavlja opcionalni parametar, pa bi trebalo da moze da bude NULL, obicno pise u dokumentaciji ako moze.
A nekad neki parametar zavisi od drugog, npr. ako je jedan 'flag' postavljen na jednom onda drugi ne moze biti NULL ili ne moze imati neki drugi 'flag'... Mozak da ti se istopi. :D

BTW. Kod mene (vs2010) nece da kompajlira ono dvoje kao parametar:

foo((COORD){1, 1}, ..., &(DWORD)0)
Ne razumem zasto bi kastovao konstantu '0' u DWORD pa uzeo adresu? Zasto ne samo 0?

EDIT:
offtopic: Kako bi preveo 'flag' na srpski u ovom kontextu, bas me zanima? :D

ozzytheking
8.4.2012, 16:27
Ni ja ne razumem, ali tako radi. Odnosno, ne moze da se napise &(DWORD)0 nego mora &(DWORD){0}.

Belphegor
8.4.2012, 16:46
Ma nisam ukucao sve u post, ovo sam probao VS2010:

typedef unsigned long DWORD;

void foo(DWORD* p)
{
*p = 1;
}

int main()
{
foo( &(DWORD){0} );
return 0;
}
error:

error C2143: syntax error : missing ')' before '{'
A sa CB-om g++ 4.6.2:
error:

error: taking address of temporary [-fpermissive]|
Sto znaci da je "(DWORD){0}" u stvari privremena promenljiva sa vrednosti 0 (adresa joj je drugacija)

EDIT: A ovo isto ne radi sa VS2010:

#include <iostream>

struct COORD
{
short x, y;
};

void foo(COORD c)
{
std::cout << "COORD( " << c.x << ", " << c.y << " )" << std::endl;
}

int main()
{
foo( (COORD){1,1} );
return 0;
}


a sa g++ radi. Mora da su neka stara sintaksna pravila?

Geomaster
8.4.2012, 21:52
@Geomaster: Bas je fora u tome da NULL ne sme da se prosledi. I ja sam se vodio tom logikom da ako prosledim NULL kao argument da funkcija nece upisivati nista u lokaciju zadatu argumentom (kao npr time(NULL)), ali to ne radi, odnosno radi kad se program pokrene normalno, ali prilikom debagovanja se javlja SEGF. I to nije slucaj samo sa tom funkcijom, nego sa svim Windows funkcijama (barem onim sa kojima sam ja radio), neke cak ne uspeju ni da urade ono za sta su zaduzene pre nego sto se javi SEGF (konkretno ReadConsoleInput()).

Sad kad pogledam ovo sto je Belphegor postavio, izgleda da ovo "opt" znaci da moze da se prosledi i NULL, ali nijedna od ovih funkcija koje ja koristim nema "opt" kao osobinu/stagod argumenta.
Onda se izvinjavam, ali stvarno, u svim APIjima koje sam koristio, nije se dogodilo da ne mogu da prosledim NULL out parametru a da program crashuje. Ima izuzetaka, naravno, kada je upravo poenta funkcije da vrati nešto u takvom parametru, kada nema smisla proslediti NULL.