Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
FBTRON
Anmeldungsdatum: 10.04.2010 Beiträge: 3
|
Verfasst am: 10.04.2010, 17:01 Titel: Array Daten an SUB's, Array Rückgabewerte von SUB's |
|
|
Hallo Experten !
Wie übergibt man eine Matrix (Array) über die Parameterliste an eine SUB und wie liefert eine Sub Rechenergebnisse (Matrix, Array) zurück an das aufrufende Programm und zwar ohne Arrays global zu deklarieren, OHNE -lang QB, OHNE -lang FBlite, OHNE -lang deprecated beim Kompilieren ?
Ich kann nicht begreifen, dass per default ab Version v0.17 alle Variablen als BYVAL an SUB's übergeben werden, das degradiert die Parameterübergabe an SUB's zur Einbahnstraße.
Wenn jemand einen einfachen Tipp hätte, ohne übermäßige Deklarationen und Umwege, wäre mir sehr geholfen . |
|
Nach oben |
|
 |
MOD Fleißiger Referenzredakteur

Anmeldungsdatum: 10.09.2007 Beiträge: 1003
|
Verfasst am: 10.04.2010, 17:06 Titel: |
|
|
Hi,
ich finde es macht schon Sinn, alle Parameter ByVal zu übergeben, wenn du aber ByRef übergeben willst, dann gib das einfach an: ByRef
edit:
Das Übergeben eines Arrays ist einfach:
Code: | Sub foo (bar() As Integer)
For i As Integer = LBound(bar) To UBound(bar)
Print bar(i)
Next
End Sub
Dim As Integer bar(1 To 3)
bar(1) = 5
bar(2) = 7
bar(3) = 1
foo(bar())
Sleep
|
|
|
Nach oben |
|
 |
FBTRON
Anmeldungsdatum: 10.04.2010 Beiträge: 3
|
Verfasst am: 10.04.2010, 17:33 Titel: |
|
|
Hi MOD,
Das Übergeben eines Arrays ist einfach: Ja, simme ich Dir zu.
Aber Dein Beispiel ist doch die "Einhabnstraße", von der ich gesprochen habe.
Sub foo (bar() As Integer)
For i As Integer = LBound(bar) To UBound(bar)
bar(i) =bar(i) * 5
Next
End Sub
Dim As Integer bar(1 To 3)
bar(1) = 5
bar(2) = 7
bar(3) = 1
foo(bar())
for i =1 to 3
print bar(i)
NextSleep
Ausgabe müßte sein
10
14
2
Noch einmal meine Frage:
Wie liefert eine SUB über die Parameterliste
Ergebnisse an das aufrufende Programm zurück,
OHNE -lang .... beim Kompilieren ?
Ich will nicht meine gesamte Sammlung SUB's mit Matrixoperationen umbauen müssen . |
|
Nach oben |
|
 |
MOD Fleißiger Referenzredakteur

Anmeldungsdatum: 10.09.2007 Beiträge: 1003
|
Verfasst am: 10.04.2010, 17:41 Titel: |
|
|
Wie gesagt, ByRef verwenden. Also die Sub so gestalten:
Code: | SUB foo (ByRef bar() AS INTEGER) |
Damit kann die Sub die Werte des Arrays verändern und die Änderungen sind auch nach dem Aufruf noch vorhanden.
edit: Vergiss ByRef anzugeben, Arrays werden immer ByRef angegeben, also funktioniert das so schon richtig. Deine Aussage über die Ausgabe ist trotzdem falsch.
Zitat: | Ausgabe müßte sein
10
14
2 |
Da du mit 5 multiplizierst, muss 25, 23 und 5 rauskommen.
Zuletzt bearbeitet von MOD am 10.04.2010, 17:51, insgesamt einmal bearbeitet |
|
Nach oben |
|
 |
nemored

Anmeldungsdatum: 22.02.2007 Beiträge: 4704 Wohnort: ~/
|
Verfasst am: 10.04.2010, 17:48 Titel: |
|
|
In der aktuellen fb-Version ist eine Array-Übergabe immer BYREF, BYVAL ist gar nicht mehr erlaubt.
FBTRON, welche FB-Version verwendest du? Bei mir lautet die Ausgabe
und genau das sollte bei einer Multiplikation mit 5 auch herauskommen. _________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Zuletzt bearbeitet von nemored am 10.04.2010, 17:49, insgesamt einmal bearbeitet |
|
Nach oben |
|
 |
FBTRON
Anmeldungsdatum: 10.04.2010 Beiträge: 3
|
Verfasst am: 10.04.2010, 17:49 Titel: |
|
|
HI MOD,
ist mit vollkommen klar.
Ab Versioin v0.17.b muß bei Übergabe mit BYREF mit -lang QB oder -lang FBlite ... kompiliert werden, das macht die Version v0.20.0b kompatibel zur Version v0.16.
Kann man -lang FBlite vermeiden ??? -lang QB vermeiden ???? |
|
Nach oben |
|
 |
MOD Fleißiger Referenzredakteur

Anmeldungsdatum: 10.09.2007 Beiträge: 1003
|
Verfasst am: 10.04.2010, 17:54 Titel: |
|
|
Da war einer schneller als mein edit...
Zurück zum Thema, du musst nicht anders compilieren nur weil du ByRef verwendest. Die Aussage ist, dass standardmäßig ByVal verwendet wird, wenn nichts anderes angegeben wird in -lang fb. Wenn du aber normal ByRef angibst, dann kannst du trotzdem in -lang fb compileren.
Nur brauchst du kein ByRef, da Arrays im gegensatz zu normalen Variablen immer ByRef sind, auch in -lang fb. |
|
Nach oben |
|
 |
Sebastian Administrator

Anmeldungsdatum: 10.09.2004 Beiträge: 5969 Wohnort: Deutschland
|
|
Nach oben |
|
 |
nemored

Anmeldungsdatum: 22.02.2007 Beiträge: 4704 Wohnort: ~/
|
Verfasst am: 10.04.2010, 18:00 Titel: |
|
|
MOD hat Folgendes geschrieben: | du musst nicht anders compilieren nur weil du ByRef verwendest. |
FBTRON hat insofern recht, dass sich das hier
Code: | Sub foo (byref bar() As Integer) |
nicht mehr compilieren lässt. Bei normalen Variablen funktioniert das problemlos.
Code: | Sub foo (byref bar As Integer) |
_________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
 |
MOD Fleißiger Referenzredakteur

Anmeldungsdatum: 10.09.2007 Beiträge: 1003
|
Verfasst am: 10.04.2010, 18:10 Titel: |
|
|
Da hab ich mich etwas allgemein ausgedrückt, also nochmal:
Arrays werden immer ByRef übergeben, egal welche Version und welcher FB-Dialekt.
ByRef muss und darf dabei auch nicht angegeben werden und ByVal darf erst recht nicht angegeben werden.
Ich finde ja, Arrays sollten auch ByVal sein, aber gut
Hab das auch gleich in der Referenz vermerkt: Arrays |
|
Nach oben |
|
 |
nemored

Anmeldungsdatum: 22.02.2007 Beiträge: 4704 Wohnort: ~/
|
Verfasst am: 10.04.2010, 18:17 Titel: |
|
|
Ich denke, der Grund für BYREF bei Arrays wird der sein, dass bei großen Arrays eine riesige Menge an Daten herumgeschaufelt werden müsste. Ansonsten gibt es ein paar seltene Fälle, in denen mir BYVAL auch lieber wäre.  _________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
 |
MOD Fleißiger Referenzredakteur

Anmeldungsdatum: 10.09.2007 Beiträge: 1003
|
Verfasst am: 10.04.2010, 18:18 Titel: |
|
|
Ja stimmt, dass könnte der Grund sein. ByVal erstellt immer Kopien und bei 10000 Elementen im Array wäre das kein Spaß. |
|
Nach oben |
|
 |
28398
Anmeldungsdatum: 25.04.2008 Beiträge: 1917
|
Verfasst am: 10.04.2010, 19:20 Titel: |
|
|
Naja 10.000 Integers sind gerade mal 40kB. Klar, wenn man da eine recht großen UDT hat... Aber eigentlich gibt es dafür heute keinen Grund mehr. Der eigentliche Grund dürfte nämlich sein, dass FB Arrays auf'm Stack speichert. Und der ist Größenmäßig doch sehr eingeschränkt.
DAS sollte man vll. doch mal ändern. |
|
Nach oben |
|
 |
Jojo alter Rang

Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
|
Verfasst am: 10.04.2010, 19:35 Titel: |
|
|
Das ist eigentlich ziemich normal, dass Parameter aufm Stack übergeben werden.  _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 |
|
Nach oben |
|
 |
28398
Anmeldungsdatum: 25.04.2008 Beiträge: 1917
|
Verfasst am: 10.04.2010, 20:57 Titel: |
|
|
afaik werden Arrays konstanter Größe aber immer im Stack gespeichert. |
|
Nach oben |
|
 |
nemored

Anmeldungsdatum: 22.02.2007 Beiträge: 4704 Wohnort: ~/
|
Verfasst am: 11.04.2010, 12:23 Titel: |
|
|
Das führt jetzt zwar etwas von der ursprünglichen Frage weg, aber zu
MOD hat Folgendes geschrieben: | Ich finde ja, Arrays sollten auch ByVal sein, aber gut  |
funktioniert immerhin das hier:
Code: | type testtyp
as integer arr(5)
end type
sub testsub(byval udt as testtyp)
udt.arr(0) = 7
end sub
dim testvar as testtyp
testsub(testvar)
print testvar.arr(0) |
_________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
 |
MOD Fleißiger Referenzredakteur

Anmeldungsdatum: 10.09.2007 Beiträge: 1003
|
Verfasst am: 11.04.2010, 13:52 Titel: |
|
|
Ja, das funktioniert, hat aber einen entscheidenden Nachteil - keine dynamischen Arrays. Man könnte das nun so machen:
Code: | Type testtyp
As Integer size
As Integer Ptr arr
End Type
Sub testsub(ByRef udt As testtyp)
udt.size = 1
udt.arr = Callocate(udt.size, SizeOf(Integer))
udt.arr[0] = 7
udt.arr[1] = 9
End Sub
Dim testvar As testtyp
testsub(testvar)
Print testvar.arr[0]
Print testvar.arr[1]
DeAllocate(testvar.arr)
Sleep |
So gehen zwar "dynamische Arrays", aber ByVal führt zum Absturz des Programms und das ganze schaut doof aus und ist auch umständlich in der Verwendung.
Eine weitere Möglichkeit wäre das hier:
http://www.freebasic-portal.de/code-beispiele/kleine-helferlein/dynamische-arrays-in-types-168.html
Sicher nicht perfekt, aber ein Anfang und ByVal funktioniert wunderbar. |
|
Nach oben |
|
 |
croco97

Anmeldungsdatum: 04.11.2005 Beiträge: 260
|
Verfasst am: 11.04.2010, 21:04 Titel: |
|
|
Um auch noch meinen Senf zum Thema zu geben:
Übergaben byvalue machen für nicht-einfache Typen (Arrays, Strings, UDTs) keinen Sinn, bzw. sind nicht sinnvoll möglich. Das ist in jeder Nicht-OOP-Programmiersprache so. Der Grund ist, dass eine richtige Kopie nur dann möglich ist, wenn ein deep copy-Konstruktor definiert ist. Und das ist sehr oft nicht der Fall.
Vielleicht habt Ihr's schon bemerkt, vielleicht auch nicht: Auch bei ganz normalen Strings gilt als Default auch in Ver. 0.20b weiterhin byref!
Um mir lange Ausführungen zu sparen: Standard ist, in solchen Fällen Zeiger zu übergeben. (Und die natürlich by value...). Weiterhin ist es guter Stil, Argumente nicht schreibend anzufassen, es sei denn, es ist der explizite Sinn der Methode (z.B. eine replace-Methode oder sowas). Dann hat man eigentlich wenig Probleme an der Front.
VG!
Croco |
|
Nach oben |
|
 |
nemored

Anmeldungsdatum: 22.02.2007 Beiträge: 4704 Wohnort: ~/
|
Verfasst am: 11.04.2010, 21:33 Titel: |
|
|
Ich frag einfach mal so: angenommen, ich möchte einer FUNCTION ein Array übergeben, die soll die darin enthaltenen Daten auch auswerten, aber auf gar keinen Fall ändern können (vielleicht schreibe ich den Inhalt der FUNCTION ja auch nicht selbst, sondern jemand anderer). Ich denke mal, mit meinem UDT-Trick müsste das klappen, aber gibt es dafür eine bessere/sinnvollere Möglichkeit? Ich glaube, die PRIVATE-Methoden in fb lassen sich recht leicht aushebeln. _________________ Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1. |
|
Nach oben |
|
 |
MOD Fleißiger Referenzredakteur

Anmeldungsdatum: 10.09.2007 Beiträge: 1003
|
Verfasst am: 11.04.2010, 21:43 Titel: |
|
|
Mit Pointern kann man Private umgehen, wenn man die Struktur des UDTs kennt: http://www.freebasic-portal.de/porticula/private-mit-pointern-umgehen-1043.html
Statt das Array in ein UDT zu packen, kannst du auch wie im Code meines vorherigen Posts das Array als Integer Ptr tarnen. Ich hab das jetzt in einen Type gepackt, kann man aber auch ohne machen und den Pointer kann man dann ByVal übergeben. |
|
Nach oben |
|
 |
|