- posted
19 years ago
wskaznik do funkcji
- Vote on answer
- posted
19 years ago
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); }
}- Vote on answer
- posted
19 years ago
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.
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
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.
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
Ale tego nie powinien bardzo optymalizowac ..
J.
- Vote on answer
- posted
19 years ago
A tak apropos - moze to nie problem z wywolywaniem funkcji, tylko w tej Przelicz wychodziles poza zakres bufora ?
J.
- Vote on answer
- posted
19 years ago
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.
- Vote on answer
- posted
19 years ago
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.
- Vote on answer
- posted
19 years ago
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
- Vote on answer
- posted
19 years ago
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.
- Vote on answer
- posted
19 years ago
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
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
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.
- Vote on answer
- posted
19 years ago
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.
- Vote on answer
- posted
19 years ago
- Vote on answer
- posted
19 years ago
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.
- Vote on answer
- posted
19 years ago
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.
- Vote on answer
- posted
19 years ago