[BASCOM] byval (by value) i byref (by reference)

Proste przykłady do częstych pytań.
ODPOWIEDZ
Awatar użytkownika
niveasoft
Posty: 1213
Rejestracja: 17 sie 2015, 12:13
Kontakt:

[BASCOM] byval (by value) i byref (by reference)

Post autor: niveasoft » 07 mar 2018, 7:19

Nie wyczerpię tematu na pewno, ale postaram się przybliżyć najważniejsze sprawy.

W Bascom możemy użyć Subów lub Funkcji.
Podstawowa różnica między nimi jest taka, że funkcja zwraca wartość i dlatego wywołanie funkcji następuje inaczej, poprzez przypisanie wartości zwracanej przez funkcję do jakiejś zmiennej. Zaraz to pokażę na przykładzie.

Kolejną sprawą jest to że Subom i Funkcjom możemy przekazywać parametry, ale nie musimy...
Najprostszy Sub lub Funkcja mogą wyglądać tak:
  1. Dim A As Byte , B As Byte , C As Byte
  2.  
  3. Sub Sumuj()
  4.  C = A + B                                                  'sub działa na zadeklarowanych zmiennych programu
  5. End Sub
  6.  
  7. Function Wynik_sumy() As Byte
  8.  Wynik_sumy = A + B
  9. End Function
  10.  
  11. 'wywołanie dla zwykłego Sub
  12.  Call Sumuj()
  13.  
  14.  'wywołanie dla funkcji ->wynik wpisujemy do zmiennej
  15.  C = Wynik_sumy()
Jak widać nie interesowałem się tu w ogóle byval ani byref ponieważ suby działały na zmiennych zadeklarowanychi zawsze są to te same zmienne.

Niestety jeśli takie działania chcielibyśmy teraz wykonać dla kolejnych zmiennych D, E i F to musielibyśmy stworzyć kolejny podobny Sub lub Funkcję.
To by było nieekonomiczne i teraz wchodzi właśnie przekazywanie parametrów.

Przekazanie byref czyli "by referece" oznacza przekazanie do Sub`a adresu zmiennych. To pozwoli Subowi czytać bezpośrednio z tych zmiennych oraz zapisywać bezpośrednio do nich.
Należy pamiętać, że do przekazania adresu potrzebne są dwa bajty dla każdej zmiennej , ale używane są tylko chwilowo z zapasu jaki mamy w $swstack.
  1. Dim A As Byte , B As Byte , C As Byte , D As Byte , E As Byte F As Byte
  2.  
  3. Sub Sumuj(byref Pierwsza As Byte , Byref Druga As Byte , Byref Trzecia As Byte)
  4.  
  5.  Trzecia = Pierwsza + Druga
  6.  
  7. End Sub
  8.  
  9.  
  10.  Call Sumuj(a , B , C)                                      'sub doda A do B i wynik zapisze w C
  11.  Call Sumuj(d , E , F)                                      'sub doda D do E i wynik zapisze w F
  12.  
Dla funkcji będzie podobnie:
  1. Dim A As Byte , B As Byte , C As Byte , D As Byte , E As Byte F As Byte
  2.  
  3. Function Wynik_sumy(byref Pierwsza As Byte , Byref Druga As Byte) As Byte
  4.  Wynik_sumy = A + B
  5. End Function
  6.  
  7. C = Wynik_sumy(a , B)
  8. F = Wynik_sumy(d , E)
Natomiast przekazanie parametrów byval czyli "by value" powoduje stworzenie kopii zmiennych i działanie na kopiach.
Stworzenie kopii oczywiście wymaga czasu. Dodatkowo proszę sobie wyobrazić przekazanie do Suba długiego stringa byval.
Czyli mamy :
  1. Dim My_string As String * 100
  2.  
  3. Sub Tnij_string(byval Jakis_string)
  4.  
  5. End Sub
  6.  
  7. Call Tnij_string(my_string)                                 'spowoduje skopiowanie stringa My_string czyli nawet 100B
Spowoduje skopiowanie stringa My_string czyli zajęcie nawet 100B pamięci SRAM!
Lepiej więc taki długi string przekazać byref i podać tylko adres jego początku dwoma bajtami ;)

Być może ciąg dalszy nastąpi jak przemyślę dalszą część :D
Pikczu
Posty: 389
Rejestracja: 17 sie 2015, 13:46
Lokalizacja: Dublin, Ireland
Kontakt:

Re: [BASCOM] byval (by value) i byref (by reference)

Post autor: Pikczu » 23 sty 2019, 21:48

Chciał bym jeszcze dodać iż mamy możliwość przekazywania do funkcji tablic.
Dla przykładu potrzebujemy zrobić XOR z wszystkich komórek tablicy więc piszemy:
  1. Config Submode = New                                        ' zeby nie deklarowac subów i funkcji
  2. Dim Tablica(6) As Byte                                      ' nasza tablica z danymi do obróbki
  3. Dim Wynik As Byte                                           ' zmienna na wynik
  4. Tablica(1) = 1                                              'przypisanie wartosci do tablicy
  5. Tablica(2) = 2
  6. Tablica(3) = 3
  7. Tablica(4) = 4
  8. Tablica(5) = 5
  9. Tablica(6) = 6
  10.  
  11. Function Xor_this(ar()as Byte ) As Byte                     '  nasza funkcja
  12.    Local Xor_ing As Byte                                    'tym czasowa zmienna na wynik z XOR moze byc lokalna
  13.  
  14.    Xor_ing = Ar(1) Xor Ar(2)                                'xorujemy
  15.    Xor_ing = Xor_ing Xor Ar(3)
  16.    Xor_ing = Xor_ing Xor Ar(4)
  17.    Xor_ing = Xor_ing Xor Ar(5)
  18.    Xor_ing = Xor_ing Xor Ar(6)
  19.    Xor_this = Xor_ing 'Ważne przypisanie wartości do funkcji musi byś ostatnią operacją  w funkcji !
  20. End Function
  21. '******************************************************************************
  22.                                                          '
  23. [b]Wynik = Xor_this(tablica(1) )[/b]                                'BARTEK słusznie zauważył ze nawias nie może być pusty podajemy index pierwszej komórki.
  24. Print "wynik= " ; Wynik
  25. End
Poprawka Bartek zauważył iż kompilator generuje ostrzeżenie jeśli w wywołaniu funkcji nawias będzie pusty Wynik = Xor_this(tablica() )
PS. dzięki za znalezienie buga
Ostatnio zmieniony 23 sty 2019, 23:10 przez Pikczu, łącznie zmieniany 1 raz.
Awatar użytkownika
niveasoft
Posty: 1213
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: [BASCOM] byval (by value) i byref (by reference)

Post autor: niveasoft » 23 sty 2019, 22:25

Pikczu pisze:
23 sty 2019, 21:48
Na co szczególnie musimy zwrócić uwagę to gdy podajemy źródło danych dla naszej funkcji i jest to tablica nawias musi być pusty.
Tutaj się wyjątkowo nie zgodzę.
Do wersji 2060 można było przekazywać tablice nawet bez nawiasów.
Teraz trzeba/można podać "adres bazowy". Sprawa jest opisana w Helpie pod hasłem Declare Function.
Na obrazku widać jak CodeExplorer płacze na czerwono :D
Jak w wywołaniu funkcji dodasz jedynkę w nawiasie to przestanie płakać.

Więc deklarując/budując funkcję ->pusty nawias, ale wywołując funkcję podajemy index.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Pikczu
Posty: 389
Rejestracja: 17 sie 2015, 13:46
Lokalizacja: Dublin, Ireland
Kontakt:

Re: [BASCOM] byval (by value) i byref (by reference)

Post autor: Pikczu » 23 sty 2019, 22:53

Bartek ale u mnie nie kwiczy o nic, nie mam błędu:
Edit chodzi ci o ten kawałek w helpie ?? podkreślony na drugim załączniku.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Ostatnio zmieniony 23 sty 2019, 22:59 przez Pikczu, łącznie zmieniany 1 raz.
Awatar użytkownika
niveasoft
Posty: 1213
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: [BASCOM] byval (by value) i byref (by reference)

Post autor: niveasoft » 23 sty 2019, 22:59

A włączyłeś prawym uchem myszy Warrningi? :F
Poniżej też wycinek z Helpa.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
Pikczu
Posty: 389
Rejestracja: 17 sie 2015, 13:46
Lokalizacja: Dublin, Ireland
Kontakt:

Re: [BASCOM] byval (by value) i byref (by reference)

Post autor: Pikczu » 23 sty 2019, 23:05

Nie włączyłem tych ostrzeżeń patrzyłem tylko na kody błędów.
No widzisz co dodatkowa para oczu potrafi :)
Zaraz z edytuje poprzedni post i usunę tą linie.
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.
ODPOWIEDZ