Seite 1 von 1

Verständnisfrage Zeiger & Proceduren

Verfasst: 14.02.2012 05:25
von BSP
Hallo.
Ich habe da mal eine Verständnisfrage:
Bisher habe ich Strings immer direkt an Proceduren übergeben, aus Sorge, ich könnte Probleme mit der Speicherverwaltung bekommen.
(Mit Zahlen ist das ja kein Problem, die sind ja intern immer gleich lang. Je nach Typ).
Nun traue ich mich aber doch mal.

Wenn ich an eine Procedure den Zeiger eines Strings übergebe
und den String dann in der Procedure verändere,
übernimmt PB die Verwaltung,
damit ich nicht bei längeren Strings ausversehen anderen Speicher überschreibe?
Ist also folgendes erlaubt?
Oder hatte ich nur glück, das nichts schlimmes passiert ist?

Code: Alles auswählen

Procedure test(*a$)
  *a$="viel Länger"
EndProcedure

a1$="Kurz"
Debug a1$

test(@a1$)
Debug a1$
Und was passiert, wenn ich einen String verändere, für den es keinen Zeiger gibt?

Code: Alles auswählen

Procedure test(*a$)
  *a$="viel Länger"
  *b$="noch viel Länger"
EndProcedure

a1$="Kurz"
b1$="Ruck"
Debug a1$
Debug b1$

test(@a1$)
Debug a1$
Debug b1$
Gruß: BSP

Re: Verständnisfrage Zeiger & Proceduren

Verfasst: 14.02.2012 10:22
von helpy
Hallo,

Hier einige Infos zu Zeigern: http://purebasic.fr/german/viewtopic.ph ... 95#p290795

*a$ solltest Du in keinem Fall verwenden. Dieser Ausdruck wird von PureBasic als normale String-Variable verarbeitet und nicht als Pointer auf einen String!

Meine Meinung:
Es ist nicht möglich einen String "ByRef" (als Referenz) an eine Prozedur zu übergeben und diesen String dort mit dem PureBasic Funktionen zu verändern!
Das Auslesen mit PureBasic Funktionen sollte möglich!

Allerhöchstens (bitte mit großer Vorsicht verwenden) ist es möglich mittels Speichermanipulation in der Prozedur einen String zu verändern, wobei der String nicht länger und auch an keine andere Stelle im Speicher verschoben werden darf.
Test mit PureBasic 4.61 Beta 1 (x64):

Code: Alles auswählen

EnableExplicit

Procedure StringRead( *aString.String )
	Protected pString.String
	Protected i
	
	PokeI(@pString, *aString)
	Debug pString\s
	
	For i = 1 To Len(pString\s)
		Debug Mid(pString\s,i,1)
	Next i
	
	PokeI(@pString, #Null)
EndProcedure

Procedure StringInvert( *aString.String )
	Protected *char1.Character, *char2.Character
	Protected temp.c
	
	*char1 = *aString
	*char2 = *aString + (MemoryStringLength(*aString) - 1) * SizeOf(Character)
	While *char1 < *char2
		temp = *char1\c
		*char1\c = *char2\c
		*char2\c = temp
		*char1 + SizeOf(Character)
		*char2 - SizeOf(Character)
	Wend
EndProcedure



Define test.s
Define sep.s = "----------------------------------------"

test = "Das ist ein Test!"
Debug "String-Variable test: " + test
Debug sep
Debug "String ByRef an Prozedur übergeben und auslesen:"
StringRead(@test)
Debug sep
Debug "String-Variable test: " + test
Debug sep
Debug "String ByRef an Prozedur übergeben und Reihenfolge umkehren:"
StringInvert(@test)
Debug sep
Debug "String-Variable test: " + test
Das Ergebnis sieht wie folgt aus:

Code: Alles auswählen

String-Variable test: Das ist ein Test!
----------------------------------------
String ByRef an Prozedur übergeben und auslesen:
Das ist ein Test!
D
a
s
 
i
s
t
 
e
i
n
 
T
e
s
t
!
----------------------------------------
String-Variable test: Das ist ein Test!
----------------------------------------
String ByRef an Prozedur übergeben und Reihenfolge umkehren:
----------------------------------------
String-Variable test: !tseT nie tsi saD
ACHTUNG: Ohne "PokeI(@pString, #Null)" Würde der String von der Prozedur StringRead freigegeben und damit gelöscht werden. Das Ergebnis sieht bei meinem Test dann so aus:

Code: Alles auswählen

String-Variable test: Das ist ein Test!
----------------------------------------
String ByRef an Prozedur übergeben und auslesen:
Das ist ein Test!
D
a
s
 
i
s
t
 
e
i
n
 
T
e
s
t
!
----------------------------------------
String-Variable test: 吀A
----------------------------------------
String ByRef an Prozedur übergeben und Reihenfolge umkehren:
----------------------------------------
String-Variable test: A吀
Ich hoffe, Du schließst daraus die entsprechenden Schlüsse ;-)

lg,
guido

Re: Verständnisfrage Zeiger & Proceduren

Verfasst: 14.02.2012 11:29
von Nino
Die Übergabe eines Strings als Prozedurparameter "by Reference" ist in PureBasic tatsächlich nicht ganz intuitiv, um es mal so zu sagen. Andererseits ist sie aber auch nicht so kompliziert, wie es teilweise immer wieder dargestellt wird. PokeI() o.Ä. braucht man dafür nicht. Folgendes funktioniert prima (getestet bis einschl. PB 4.60):

Code: Alles auswählen

Procedure AendereString(*str.String)
   *str\s + " Welt! Die Sonne scheint vom Firmament."
EndProcedure

Define text.String
text\s = "Hallo"
AendereString(@text)
Debug text\s             ; zeigt "Hallo Welt! Die Sonne scheint vom Firmament."
Grüße, Nino

Re: Verständnisfrage Zeiger & Proceduren

Verfasst: 14.02.2012 12:10
von helpy
Hi Nino!

Stimmt! Auf diese Weise (Strukturen mit Strings) können Strings "by reference" übergeben werden.

Da muss man sich aber auch drann gewöhnen statt String-Variablen (var$ oder var.s) grundsätzlich var.String und var\s zu verwenden und das ist sicher gewöhnungsbedürftig.

lg,
guido

Re: Verständnisfrage Zeiger & Proceduren

Verfasst: 14.02.2012 17:09
von Nino
Hi helpy!
helpy hat geschrieben:und das ist sicher gewöhnungsbedürftig.
Da stimme ich Dir unbedingt zu. Ich empfinde das auch als relativ unelegant, aber etwas besseres ist mir nicht bekannt. Und immer noch besser, als statt dessen eine globale Variable zu verwenden (von wenigen Ausnahmen vielleicht abgesehen). Insgesamt brauche ich eine Stringübergabe "by reference" nur selten, aber manchmal ist es halt sehr nützlich. Daher wäre es IMHO v.a. für Anfänger gut, wenn das in der PB-Hilfe offiziell dokumentiert wäre.

Grüße, Nino

Re: Verständnisfrage Zeiger & Proceduren

Verfasst: 14.02.2012 22:44
von BSP
Hallo.
Danke für Eure Antworten.
Ich habe mit meiner Idee noch ein wenig "herumgespiel"
und bekam wiederholt die Meldung "Ungültiger Speicherzugriff".

Also: Die Gedanken schnell wieder vergessen.
Schade eigentlich. Sah so schön einfach aus.

Gruß: BSP