es_91 hat geschrieben:Variablen würden zu der Zeit deklariert, wo ich im Quelltext z.B. Protected schreibe.
Nein.
Define, Globale, Threaded, Protected, Stattic usw. sind alle Compiler-Befehle, die beschreiben, wie Variablen im Programm eingearbeitet werden sollen, wenn sie auftreten.
Für eine Selektierung musst du dann CompilerSelect und CompilerCase nutzen.
In der Tat scheint da der Compiler etwas inkonsistent zu sein. Aber vielleicht liegt es auch daran, dass man ja auch ohne Define mehrmals Variablen deklarieren kann. Es gibt ja manche Purebasicler, die z.B. hinter jedes Vorkommnis einer Variablen immer den Typ dahinter schreiben, auch wenn es beim ersten mal schon reichen würde.
Eigentlich wäre es schon cool, wenn der Compiler dann meckert, wenn man etwas mehr als einmal deklariert. Es stört zwar das Programm nicht, aber es ist einfach inkonsistent. Zumindest bei EnableExplicit könnte man einbauen, dass er bei einer Doppeldeklaration meckert.
Procedure MyProcedure ()
Protected MyVar
MyVar = 1
Select MyVar
Case 1, 2
Protected b
Select MyVar
Case 1
b = 5
Case 2
b = 6
EndSelect
EndSelect
Debug b
EndProcedure
MyProcedure ()
Ach, und nochwas:
STARGÅTE hat geschrieben:Für eine Selektierung musst du dann CompilerSelect und CompilerCase nutzen.
Für unerfahrene Nutzer (wie mich vor zwei Stunden): Das funktioniert so nur mit Konstanten!!!
es_91 hat geschrieben:Hier der Weg, wie ich das (umständlich) umgangen bin (ich wollte eben die Variablen nur deklarieren, wenn sie wirklich gebraucht werden):
Die Variablen werden immer "deklariert", bzw. "umgesetzt". Du könntest zwar mit CompilerIf arbeiten, dann werden nur die
Variable "deklariert", bzw. "umgesetzt", die benötigt werden, aber die anderen sind nicht Verfügbar.
Wenn ich das ganze richtig verstanden habe, machst Du etwas vollkommen sinnloses. Ich empfehle, alle Variablen nur einmal
am Anfang zu "deklarieren". Mit "deklarieren" meine ich Declare, Protected, Statik, Global. Bedingungsabhängig geht das nicht
(ausser CompilerDirektiven, die nur einmal ausgewertet werden).
Ansonsten den Tipp von NicTheQuick beachten.
Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
ts-soft hat geschrieben:Wenn ich das ganze richtig verstanden habe, machst Du etwas vollkommen sinnloses.
Ich weiß jetzt nicht, ob ich Dich richtig verstanden haben. Variablen deklarieren kostet doch Zeit, richtig? Dann will ich diese Nanosekunden nur dann abarbeiten lassen, wenn ich die Variablen wirklich brauche.
Unabhängig davon denke ich, dass sich der Code besser lesen lässt, wenn Variablen dort deklariert werden, wo sie gebraucht werden.
ABER: Natürlich hast du Recht, mein Code-Stil hat nicht den vollen Effekt, wenn Variablen in Prozeduren immer am Start deklariert werden. Und auch der Code da oben hat dann so keinen Sinn, außer der Lesbarkeit halber.
NicTheQuick hat geschrieben:Wenn du Stack sparen willst...
Das verstehe ich gerade irgendwie nicht. Wie kann man sich einen Stack in diesem Fall vorstellen?
Und noch eine Frage:
Ist das bei anderen Programmiersprachen auch so, C, C++, BASIC?
Wenn es nicht den zehnfachen Speicher benötigte und wesentlich langsamer währe, würde ich vielleicht für Variablen nur noch diesen code verwenden... ich wünschte mir eine Sprache, die Variablen zur Zeit der Deklaration erst deklariert.
ts-soft hat geschrieben:Wenn ich das ganze richtig verstanden habe, machst Du etwas vollkommen sinnloses.
Ich weiß jetzt nicht, ob ich Dich richtig verstanden haben. Variablen deklarieren kostet doch Zeit, richtig? Dann will ich diese Nanosekunden nur dann abarbeiten lassen, wenn ich die Variablen wirklich brauche.
Die Deklaration der Variablen kostet keine Zeit, jedenfalls nicht mehr als "OnTheFly" deklarierte. Die ausführungsgeschwindigkeit Deiner Exe wird davon nichts bemerken
Die Variable als solches ist in der Exe garnicht mehr vorhanden, nur noch Adressen.
es_91 hat geschrieben:
Unabhängig davon denke ich, dass sich der Code besser lesen lässt, wenn Variablen dort deklariert werden, wo sie gebraucht werden.
Meiner Meinung nach und der vieler anderer Programmierer auch, sowie auch in manch anderen Programmiersprachen
erforderlich, sollten Variablen möglichst am Anfang des Geltungsbereichs deklariert werden. Also: ProgrammAnfang,
ProcedureKopf usw.
Entweder gleich mit zugewiesenem Wert, oder erstmal ohne Wert, wenn die Wertzuweisung erst später im Code erfolgt.
Ausnahmen bestätigen die Regel
PS: Der Compiler deklariert (gibt bekannt), grundsätzlich alle Variablen die im Code auftauchen! Lediglich durch Compiler-
direktiven ausgeschlossene bleiben unbekannt.
EnableExplicit kostet keine Zeit und trägt nur zur Sicherheit bei, hat aber keinen Einfluß auf generierte Exe!
Macht euch mal langsam frei von diesen komischen Vorstellungen, PureBasic ist ein Compiler, kein Interpreter!
Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Ich müsste jetzt ganz schön weit ausholen um dir erklären zu können, was ein Stack und ein Heap ist. Jedenfalls kann ich dir kurz und knapp das hier sagen:
Im Stack werden alle Variablen abgelegt, die du nicht explizit mit AllocateMemory erstellst.
Das heißt alles, was innerhalb Procedures und Protected ist, wird auf dem Stack gespeichert. Und das schöne ist: Der Stack ist schon da. Der muss nicht erst alloziert werden, wenn die Procedure aufgerufen wird. Deswegen hat er auch nur eine bestimmte Größe, wodurch es bei zu vielen verschachtelten Procedure-Aufrufen zu einem Stackoverflow kommen kann. Wird eine Procedure aufgerufen, wird automatisch für alle Variablen, die in der Procedure vorkommen, entsprechend viel Platz auf dem Stack reserviert, damit der innerhalb der Procedure für die Variablen genutzt werden kann. Wird die Procedure verlassen, wird der Speicher wieder "freigegeben", sodass ein nächster Procedure-Aufruf soviel davon nutzen kann, wie er braucht.
Alles, was Define, Global, Static, Shared oder Threaded ist, liegt normalerweise auf dem Heap. Aber das schon von Programmstart an. Der Compiler weiß ja schon während dem Kompilieren wie viel Speicher er insgesamt für alle Variablen diesen Typs braucht. Und er weiß auch, dass man diese Variablen nicht mehr freigeben kann innerhalb des Programms. Oder hast du mal versucht eine mit Define definierte Variable wieder zu "Undefinen"? Das schöne ist jetzt, dass er weiß wie viel Speicher er insgesamt für all diese Variablen braucht und dann reserviert er diesen Speicher am Stück sozusagen mittels 'AllocateMemory()' und weist jeder dieser Variablen einen Platz innerhalb dieses Speicherblocks zu.
Du siehst. Während dem Programmverlauf wird nirgendwo Zeit dafür gebraucht um Speicher für Variablen zu allozieren oder freizugeben. Nicht mal in Procedures. Der Speicher ist nämlich schon die ganze Zeit da und steht dem Programm zur Verfügung. Deswegen kann es dadurch auch nie dazu kommen, dass der Speicher für dein Betriebsystem oder andere Prozesse mal knapp wird, wenn man eine Procedure zu oft rekursiv aufruft. Vom Stack gibt es nämlich nur eine bestimmte Menge. Je nach Betriebssystem-Einstellung. Kann man aber auch per Prozess einstellen.
Aber so ganz stimmt das natürlich nicht, was oben steht. Es gibt ja auch noch Strings als nativen Datentyp in Purebasic. Strings sind dynamische Inhalte und werden ebenfalls auf dem Heap gespeichert, allerdings kann sich die Menge an Speicherplatz, die ein String braucht, während dem Programmverlauf ändern. Deshalb passiert es hier öfter, dass der Speicher neu alloziert wird und der alte wieder freigegeben wird. Zum Beispiel, wenn du einen String ein gutes Stück verlängerst, indem du einen anderen String dran hängst. Dann wird zuerst neuer Speicher alloziert, beide Strings in diesen rein kopiert und dann der Speicher des alten Strings wieder freigegeben.
Jetzt habe ich doch weiter ausgeholt als gewollt, aber ich hoffe dir ist nun klar, dass du hier an etwas herum optimierst, wo es nichts zu optimieren gibt. Um genau zu sein, gibt es nicht mal einen Unterschied, ob man 100 Protected-Variablen in einer Procedure hat oder nur eine. Beide Male wird lediglich der Stackpointer um eine bestimmte Weite verschoben. Ansonsten empfehle ich dir auch ein bisschen in Wikipedia zu Stack, Heap, Stackoverflow zu schmökern.
Achja, in C und C++ ist das ganze auch so. Und wahrscheinlich ín allen anderen Sprachen, die in Maschinensprache kompilieren, ebenfalls. Denn darauf baut die Hardwarearchitektur deines PCs auf.