wskaznik do funkcji

Loading thread data ...

Ponizej kompletny przyklad. Tak jakby wywolujac funkcje "funckja(bufor)" on jakby zwalnial pamiec dla funkcji "dzialaj"; Czy to jest normalne ???

ynio

typedef void (*WYN)(unsigned char*);

code unsigned char napis[]="dupa wolowa";

void Przelicz(unsigned char* nap){

}

void dzialaj(unsigned char adres,unsigned char* wysw,WYN funkcja){

unsigned char bufor[5];

//tu adres = 0x80 funkcja(bufor); //tu juz adres = 0

adres= adres + 1;

}

main(){

while(1){ dzialaj(0x80,napis,Przelicz); }

}
Reply to
ynio

To jest zapisane poprawnie, ale nie ma żadnego sensu - "wysw" jest nieużywany, "adres" tak naprawdę również jest nieużywany, "bufor" jest niezainicjalizowany, a jak mniemam powinien (chociaż nie musi) być. Najprawdopodobniej kompilator zauważył te niekonsekwencje i dokonał odpowiednich optymalizacji.

Regards, /J.D.

Reply to
Jan Dubiec

Tez mi sie tak wydaje.

Nie bardzo mial prawo - musialby bardzo globalnie patrzec zeby moc to zrobic. A przy takim zapisie to skad ma wiedziec ze mniejszy fragment nic nie robi ?

Podeslij wydruk assemblerowy tego przykladu, moze dodajac putc(bufor[0]) przed i po wywolaniu [printf bedzie za dlugi]. Moze wtedy cos zobaczymy podejrzanego.

Moze blad w kompilatorze, moze trzeba mu dorzucic jakies slowa kluczowe ?

J.

Reply to
J.F.

Ale tego nie powinien bardzo optymalizowac ..

J.

Reply to
J.F.

A tak apropos - moze to nie problem z wywolywaniem funkcji, tylko w tej Przelicz wychodziles poza zakres bufora ?

J.

Reply to
J.F.

On Wed, 16 Mar 2005 14:40:59 +0100, "ynio" snipped-for-privacy@poczta.onet.pl> wrote: [.....]

Sądzimy że to normalka. Ale skoro kompilator zoptymalizował kawałek kodu czego wg. Ciebie nie powinien był robić, to jest prawie pewne, że ów kawałek kodu jest do bani. Nie wiem czego konkretnie oczekujesz, ale jeśli chcesz aby kompilator za bardzo nie przesadzał z optymalizacją, to możesz używać modyfikatora "volatile" do deklaracji niektórych zmiennych. IMO daje lepszą kontrolę nad kodem niż nieprzenośne pragmy czy też opcje kompilatora.

Regards, /J.D.

Reply to
Jan Dubiec

IMO jak najbardziej powinien. Np. wyrażenie adres = adres + 1; umieszczone na końcu funkcji nie ma żadnego skutku (przy deklaracji zmiennej adres takiej jak w przykładzie). Więc nadaje się do wywalenia, tzn. optymalizacji. :-) Dobry kompilator, czyli gcc, :-) przy optymalizacji O3 wogóle wywali wywołanie funkcji działaj i z main-a od razu zawoła funkcję Przelicz.

Regards, /J.D.

Reply to
Jan Dubiec

No wlasnie nie, specjalnie dawalem spory buforek. No nic w razie to taki manewr pomaga.

W koncu i tak to rozwiazalem wszystko nie uzywajac wskaznikow do funkcji. Teraz ladnie smiga i nie trzeba zmniejszac optym.

Pozdr ynio

Reply to
ynio

No wlasnie nie.

Pusta funkcje Przelicz moze zamienic na jednego ret. adres++ moze wywalic, ale funkcja(bufor) juz nie - bo nie wie co jest w zmiennej "funkcja". Tzn moglby wiedziec, ale to juz by chyba za duzo optymalizacji bylo :-)

Owszem, moglby w ogole parametr "adres" potraktowac jako przestrzen robocza bo nieuzywany ... ale skoro ynio stwierdzil ze sie zmienia .. to chyba jednak uzyl.

No chyba ze ynio stwierdzil to debuggerem, a kompilator przydzielil tej zmiennej rejestr i skoro nie uzywana to nie uznal za sensowne zachowywac na czas wywolania *funkcja.

Stanowczo trzeba zajrzec w assemblerka.

J.

Reply to
J.F.

Analizowalem sobie znowu i faktycznie gdy cos sie robi ze zmienna to przetrzymuje. Ale w moim przypadku tez robilem, adres bezposrednio przekazywalem do innej funkcji, tak samo jak adresy do buforow. No nic powstal ciekawy temat:) W razie gdy cos nie dziala nalezy wylaczyc optymalizacje i zobaczyc czy to nie taka przyczyna :)

Pozdrawiam ynio

Reply to
ynio

On Wed, 16 Mar 2005 19:02:36 +0100, "ynio" snipped-for-privacy@poczta.onet.pl> wrote: [.....]

Jeśli to ma być szybkie, to sam zaimplementuj w assemblerze mnożenie i dzielenie liczb wielobajtowych. Możesz też stablicowac wartość wyrażenia 3600*z (133 liczby czterobajtowe) albo nawet całego wyrażenia jeśli masz dużo pamięci programu. Możesz też użyć taniego mikrokontrolera 32-bitowego i zapomnieć o takich problemach. :-)

Regads, /J.D.

Reply to
Jan Dubiec

No i kompilator (gcc -O3) robi to sprytnie - generuje poprawne i zoptymalizowane ciało funkcji działaj() (bo być może będzie ona wołana z innego modułu programu), ale w main-ie woła od razu Przelicz(). Nie sprawdzałem tego, ale wydaje się być całkiem naturalne, że gdyby działaj() było zadeklarowane z modyfikatorem static, to kompilator nie wygenerowałby kodu dla tej funkcji.

Gcc 3.4.0 dla ix86 z właczoną optymalizacją O2 lub mniejszą tego nie wie, ale z O3 już wie. :-)

No właśnie zmnienia się dlatego, że najprawdopodobniej miejsce przez które została przekazana wartość adres (czyli, w zależności od calling convention, rejestr lub komórka pamięci na stosie) zostało użyte jako owa "przstrzeń robocza", a konkretnie jako miejsce przez które przekazuje się z kolei argument do funkcji funkcja(), czyli po prostu wskaźnik (adres) tablicy char-ów.

Ja to jestem praktycznie pewny, że stwierdził to na podstawie wskazań symulatora/debuggera. :-)

Oczywiście. Tak też zrobiłem, aczkolwiek dla ix86. :-)

Regards, /J.D.

Reply to
Jan Dubiec

Wstawka assemblerowa ? Mnozenie longa [eee - 24 bit starcza] przez 8 bit jest zgrabne, dzielenie przez 8 bit tez. Hm .. a moze kompilator o tym wie ?

J.

Reply to
J.F.

On Thu, 17 Mar 2005 22:58:12 +0100, J.F. <jfox snipped-for-privacy@poczta.onet.pl> wrote: [.....]

Nie sądzę. Dlatego sugerowałem napisanie własnych funkcji w assemblerze.

Regards, /J.D.

Reply to
Jan Dubiec

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.