09A.1 Kästchenroboter, Teil 4, malloc, Zeiger wie Arrays
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 35 | |
Author | ||
License | CC Attribution - NonCommercial - ShareAlike 3.0 Germany: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this | |
Identifiers | 10.5446/9597 (DOI) | |
Publisher | ||
Release Date | ||
Language | ||
Producer |
Content Metadata
Subject Area | |
Genre |
1
4
30
31
34
00:00
OvoidRobotPrint <4->CountingInformationVariable (mathematics)Programmer (hardware)CompilerComputer fileLaufzeitSoftware developerMemory managementC-CompilerPointer (computer programming)Constraint (mathematics)Sound effectForestRobotC++Logical constantHöheComputer animation
06:05
RobotInformationEIBPrint <4->CountingOvoidFreewareOperating systemCalculationVariable (mathematics)Programmer (hardware)Similarity (geometry)HöheCASTPointer (computer programming)IP addressInterior (topology)FreewareWritingZahlFunction (mathematics)UmrechnungMass storageComputer animation
12:10
Engineering drawingDiagram
12:36
RobotInformationInventor <Programm>OvoidCountingComputer scienceZugriffUmrechnungEncapsulation (object-oriented programming)LengthInterface (computing)IndexNumberMischung <Mathematik>Engineering drawingDiagramComputer animation
17:55
DownloadCodeRobotRegulärer Ausdruck <Textverarbeitung>Inventor <Programm>ExpressionPrint <4->OvoidRandom numberZugriffComputer fileTerminal equipmentNumberHöhePointer (computer programming)Two-dimensional spaceIP addressPrint <4->NullArray data structureFile viewerZahlVariable (mathematics)HauptspeicherUmrechnungMusical ensemblePerimeterComputer animation
Transcript: German(auto-generated)
00:02
Das ekligste Thema bei C und C++, das sind die Zeiger. Hier könnte ich jetzt Zeiger verwenden, für folgenden Effekt. Wenn ich nicht schon beim Programmieren weiß, wie groß dieses Feld wird, sondern erst zum Beispiel durch eine Benutzereingabe feststelle,
00:21
das sollen 20 mal 30 Felder werden, oder durch eine Messung feststelle, ich muss jetzt hier 10 mal 12 Felder unterbringen, dann habe ich ein kleines Problem. Der Compiler will hier, wenn ich es so schreibe, sofort beim Kompilieren wissen, wie hoch und wie breit das Feld ist. Ich kann ihm nicht später sagen, wie hoch und wie breit das Feld ist.
00:42
Fußnote in C99 kann man das schon, in C++ kann man es nicht. Im typischen C, aller Welt C, kann man es nicht. Wenn Sie das so schreiben, baue mir ein Array von dieser Größe, dann will der typische C-Compiler da wissen, wie breit und wie hoch das Feld ist, ohne Wenn und Aber.
01:03
Das muss definiert sein. Das kann nicht erst später mit einer Benutzereingabe zur Laufzeit des Programms kommen, oder mit einer Messung zur Laufzeit des Programms, oder aus irgendwelchen Konfigurationsdateien gelesen werden. Das muss einkompiliert sein, wie groß dieses Feld ist. Das ist die übliche Anwendung jetzt für Zeiger- und für Speicherverwaltung.
01:23
Ich verwalte meinen Speicher selbst, nicht dass der Compiler das für mich tut, dass er das jetzt anlegt, 8 mal 6 dieses Feld, oder 6 mal 8 genauer gesagt, sondern dass ich das zur Laufzeit selber mache. Was mir vorschwebt, ist, dass ich hier diese Initialize-Funktion tatsächlich was mitgebe,
01:42
dass ich, wenn ich die Bibliothek aufbaue, der Initialize-Funktion sagen kann, es soll so breit sein und es soll so hoch sein, und die Initialize-Funktion baut es dann so breit und so hoch. Dann gehen wir mal in die Robot H. Also was mir vorschwebt, dass ich hier bei Initialize schreibe,
02:04
wir haben gerade überlegen welche Reihenfolge sinnvollerweise, erst die Breite, int, width, int, height, x, y. Das schwebt mir vor. Ich möchte den Initialize-Funktion sagen, jetzt mach doch mal ein Feld, 30 mal 40. Was eben, ja natürlich genauso, was dann eben so nicht mehr funktioniert.
02:26
Da muss man sich etwas anders aus der Affäre lügen. Das heißt, ich müsste hier auch in Main den Aufruf anders haben. In Main müsste der Aufruf hier sein, von Initialize so was, mach mal 8 breit und 7 hoch.
02:49
Aber dann ist das schon zu spät. Für dieses hier wäre es dann einfach schon zu spät. Der Compiler will hier Konstanten sehen, der Compiler will keine Variablen sehen, die ihm da übergeben werden zur Laufzeit.
03:03
Was ich also mache, ist jetzt, ich reserviere mir so viel Platz wie ich brauche, zu Fuß. Das muss hier dann hinkommen. Also, wie machen wir das mal in voller Weise.
03:22
Ich will ja überall nachher wissen, wieder in dieser ganzen, überall ist gut. In dieser gesamten C-Datei will ich wissen, was in dem Feld drin steht. Eine der ersten Geschichten, von der man sich verabschieden muss, ist es zweidimensional zu machen.
03:42
Es geht unter gewissen Einschränkungen zweidimensional, wenn ich nämlich die innere Dimension kenne. Ansonsten muss ich mein Feld selbst umbauen. Ich mache es eindimensional. Das ist dann, was ich mir speichere. In der Form steht das dann nachher. Das hier wird ein Zeiger irgendwo in den Speicher rein.
04:02
Einfach nur eine Hausnummer. An dieser Stelle steht ein unsigned character, den ich dann irgendwie setzen kann und auch wieder lesen kann. Ich sollte mir noch merken, wie viel da stehen muss ich mir nicht merken, weil ich merke mir Breite und Höhe.
04:20
Also der fliegt raus. Ich merke mir nur noch die Hausnummer des ersten. Und ich merke mir hier jetzt nicht mehr mit dem Define. Das ist ja sehr hässlich. Ich merke mir mit StaticInt, was die Breite ist. Und ich merke mir hier mit StaticInt, was die Höhe ist.
04:47
Wir sehen, oh, das ist nicht richtig gut. Witz, Witz, welchen meine ich jetzt? Da sind wir vielleicht ein bisschen vorsichtiger. Den nenne ich mal W und den nenne ich mal H. Wenn Initialize aufgerufen wird, dann sagen wir Width ist gleich W und Height ist gleich Height.
05:08
Wie wird das? Height ist gleich H. So soll das nachher funktionieren. Jemand ruft zu Beginn seines Programms Initialize auf und sagt 13, 42. Und dann möchte ich mir merken, 13 soll jetzt demnächst die Breite sein und 42 soll die Höhe sein.
05:25
All das mit Static hier verziert, das nur in dieser C-Datei sichtbar ist. Wir sehen, das habe ich jetzt hier umbenannt, W und H. Um in keine Komplikation mit den Namen zu kommen, das mache ich hier vielleicht auch mal in der Header-Datei.
05:41
Das wäre nicht nötig in der Header-Datei, aber ist vielleicht leichter dann zu verstehen, wenn ich hier auch W und H schreibe. Hier könnten Sie auch Carl und Anton schreiben an der Stelle. Es wird keinen stören. Hauptsache Integer.
06:01
So, damit habe ich mir gemerkt, wie groß das Feld sein soll. Und jetzt möchte ich so viel Speicherplatz einrichten. Das ist MemoryAllocate, MemoryAllocation oder wie auch immer man diesen Befehl in Langschrift nennt, MLOG.
06:21
Speicherplatz reservieren, wenn Sie so wollen. Ich muss Ihnen sagen, wie viel Speicherplatz, wie viel Zellen brauche ich, W mal H Bytes brauche ich. Wenn das Ding W Breit und H hoch sein soll, soll es W mal H so sein. So viel Bytes bitte reservieren. Und das liefert MemoryAllocate dann zurück.
06:47
Die Adresse auf das erste Byte, was er reserviert hat in dieser Form. Um es hübser zu schreiben, würde ich jetzt hier tatsächlich sogar das hinschreiben. Sie wird das schon irgendwie deichseln, aber hübscher wäre das. So sieht das nachher aus.
07:01
Gib mir mal einen Speicherbereich von so und so viel Bytes. Wenn Sie sagen drei Breit und vier hoch, zwölf Bytes. MLOG 12 sagt ihm, such mir mal einen Speicherbereich von zwölf Bytes. Und gib mir ein Zeiger auf das erste davon zurück, auf das erste Byte davon.
07:20
Und den speichere ich mir jetzt hier in meiner Variablen Field. Mit dem Hinterkopf weiß ich, muss ich mir selber merken, oh, da waren zwölfe drin. Und nicht dreizehn und nicht fünfzehn. So sieht das dann aus. Ich bitte beim System um Speicher. Das ist MemoryAllocate. Denn MemoryAllocate liefert irgendeinen Zeiger zurück. Es gehört sich, dass Sie den in den richtigen Zeiger umbiegen.
07:43
Hier mit runden Klammern. Wir kennen das ja schon von Long. Wenn wir sowas hier haben. Long von X durch Y. Das hatten wir schon. Das X, wenn es ein Int ist, auf einen Long umbiegen. Das ist, wenn ich durch das andere teile, auch weiterhin mit der Größe von Long rechnen.
08:02
Sowas ähnliches. Casten. Hier genauso, was aus dem MemoryAllocate rauskommt. Den Zeiger casten. Auf einen Zeiger von der richtigen Sorte. Ich möchte ja unseind Characters haben. Unser Stern hier hinten sagt Zeiger. Dieses Field ist dann wie eine Hausnummer.
08:20
Nicht das echte Ding. Nicht das Haus. Sondern die Hausnummer. Nur ein Zeiger darauf. Und ich kann dann eben fragen, wer unter dieser Hausnummer wohnt, sozusagen. Oder wer auch an der nächsten Hausnummer wohnt. Wenn ich das hier mache. Den Speicher reservieren gehört sich eigentlich auch, dass ich am Ende den Speicher wieder frei gebe.
08:46
Das wäre sinnvoll. Das heißt, neben einer Initialize-Funktion, im Hauptprogramm bin ich jetzt. Neben einer Initialize-Funktion sollte es auch eine Funktion Release oder Free oder ganz konsequent benannt werden. Ich nenne sie jetzt mal Finalize.
09:03
Funktion geben. Paare ich zu diesem Initialize. Initialize baut alles auf in der Bibliothek. Und wenn ich sage Finalize oder Release oder Free, sollte dann alles wieder abgebaut werden. Also noch eine extra Funktion hier in Robert H.
09:21
Da schreibe ich einfach das Initialize drunter. Void Finalize. Void. Und die Funktion soll dem System einfach sagen, okay, den Speicher brauche ich jetzt nicht mehr. Let's see, was haben wir hier. Schreibe ich das unter das Initialize. Ich schreibe es unter das Initialize.
09:42
Finalize. Hier sage ich Free. Das ist der Befehl, um zu sagen, was. Das liebe System, was du jetzt hier reserviert hast, unter dieser Adresse, das brauche ich jetzt nicht mehr.
10:01
Das kann sich jemand anderem geben oder für irgendwas benutzen. Das sollte dann paarig sein. Problematisch ist, wenn es nicht paarig ist, wenn man mehr reserviert, als man später wieder frei gibt, heißt das, dass man irgendwie Speicher auf ist und irgendwann Speicher fehlt. Wenn man mehr frei gibt, als man vorher reserviert, wird das System irgendwann auf die Barrikaden gehen und sagen, halt, hier ist noch etwas faul.
10:29
Dieses Free passiert sowieso automatisch bei Programmende. Das machen die Betriebssysteme oder auf dem Launchpad gibt es ja dann in diesem Sinne kein Betriebssystem. Das macht das System von selbst. Wenn Sie das ganz zum Ende vergessen, wird aufgeräumt.
10:40
Also Sie müssen keine Angst haben, wenn Sie es vergessen oder wenn das Programm abstürzt, dass dann so und so viel Speicher noch belegt ist, das wird dann von selbst gemacht am Programmende. Nur zwischendurch muss man aufpassen, dass man nicht zu viel Speicher verbraucht, weil man nur reserviert und nur reserviert und nie wieder frei gibt.
11:01
So, jetzt haben wir das paarig. Ich habe hier meine Bytes und nun kommt der Ärger, dass ich jetzt auf diese Bytes auch noch zugreifen muss. Was ich schreiben kann ist Field von i, aber was ich nicht schreiben kann ist Field von ij.
11:22
Ein Zeiger verhält sich wie ein eindimensionales Array. Das heißt, ich muss jetzt umrechnen. Ich habe ein eindimensionales Array mit der richtigen Breite und der richtigen Höhe. Ich muss nur die ganze Zeit umrechnen. Ein Array aus drei Zeilen und vier Spalten.
11:46
Wenn ich danach dem Feld 1, 2 frage, heißt das, gehe zur Zeile Nummer 1, Zeile Nummer 0, Zeile Nummer 1. Das ist die Zeile Nummer 1 und da gehe zur Spalte Nummer 2, Spalte Nummer 0, Spalte Nummer 1, Spalte Nummer 2.
12:03
Hier sind wir, der ist das. Was im Speicher steht, ist eine lineare Folge von Bytes, zwölf Bytes.
12:21
Zwölf Bytes stehen dafür im Speicher. Wenn ich so drauf zugreife, fällt mir das nicht so richtig auf, dass da zwölf Bytes stehen. Wo finde ich dieses Byte, das mit der Nummer 1, 2 im Speicher? In der Tat, an der siebten Stelle, wenn Sie mit 1 anfangen zu zählen, an der siebten Stelle. 1, 2, 3, 4, 5, 6, 7.
12:43
1, 2, 3, 4, 5, 6, 7. Da muss der stehen. Da muss der stehen im Speicher. In dieser Form hier ist das so einfach hingeschrieben. Im Speicher steht es anders. Mit Memory Allocate kriege ich linearen Speicher.
13:01
Das heißt, ich muss mir jetzt hier überlegen, wie ich die Umrechnung mache. Wie rechnen Sie um? Von 1 und 2, was ist dieser eindimensionale Index, den ich da geben muss? Ich sehe gerade, was irritierend ist, dass ich hier mit 1 anfange zu zählen. Hier in diesem linearen Array, das ist also der siebte in diesem Array.
13:24
Aber wenn ich jetzt C frage, ist das ja 0, 1, 2, 3, 4, 5, 6. Das heißt, C muss ich die Zeile 6 geben, um hier den siebten zu kriegen. Und das ist dann anscheinend die 1 sagt, ich brauche die 4 in der ersten Zeile.
13:44
Und dann kommen noch die 2 dazu. Das habe ich dann tatsächlich gerechnet. Einmal 4 plus 2. So komme ich auf diese Zeile 6, die ich C dann übergeben muss. Also wenn Sie einen zweidimensionalen Array haben, ich gehe in die Zeile mit der Nummer 1 und in die Spalte mit der Nummer 2.
14:02
Bei einer Breite von 4 müsste in diesem eindimensionalen Array an dieses Element mit der Nummer einmal die Breite, also die Zeilennummer, mal die Breite plus die Spaltennummer gehen. Das wäre die Umrechnung. Dieses hier macht C automatisch beim zweidimensionalen Array.
14:23
Also wenn Sie beim zweidimensionalen Array zum Beispiel etwas hinschreiben, was viel zu groß ist, wenn Sie hier hinten 500 reinschreiben, dann versucht er jetzt nicht in die 500 zur Spalte zu gehen, sondern er macht einfach weiter, weil er ganz dumm genau das rechnet, was da unten steht und nichts anderes.
14:42
Da ist ziemlich wenig Intelligenz drin. Andere Sprachen sind da ein bisschen intelligenter, brauchen dafür aber auch mehr Zeit. Also die Umrechnung ist, was in der Zeile steht, die Nummer der Zeile mal die Breite plus die Nummer der Spalte. So komme ich von zweidimensional auf linear.
15:03
Das heißt hier, bei diesem Zugriff müsste also stehen, die Nummer der Zeile, das ist offensichtlich i, die Nummer der Zeile mal die Breite plus j.
15:23
Das wäre jetzt dieser Zugriff umgemodelt auf eindimensional. So kriegen wir das hin mit denen hier. Und das müsste ich jetzt überall tun, wo das hier benötigt wird. Mal sehen, mal sehen, mal sehen, mal sehen.
15:47
Oh, das wird spannend. Y von X. Ich schreibe es mal erstmal so dahinter. Die Nummer der Zeile plus die Spalte.
16:02
Y ist die Nummer der Zeile plus die Spalte. So sieht das aus. Ich glaube, den brauche ich gleich noch ein paar Mal. Y an X genau derselbe, Y an X derselbe,
16:20
Y an X nochmal derselbe, ij, die Nummer der Zeile mal die Breite plus die Nummer der Spalte. Das müsste ich noch in der Zwischenablage haben.
16:42
Wunderbar. Das sollte es sein. Wir sehen, das ist jetzt wieder etwas zur Informatik. Was ich geändert habe, ist nur in dieser C-Datei. Ich habe die Initialize-Funktion zwar in der Header-Datei geändert, dass man jetzt von außen sagen kann, so breit und so hoch soll das Feld werden.
17:03
Aber mein Hauptprogramm ist ansonsten gleich geblieben. Die Header-Datei, diese Schnittstelle, wie das so schön heißt, ist ansonsten gleich geblieben. Und die ganzen Änderungen hier habe ich nur in der C-Datei gemacht. Das ist Kapselung. Was ich hier veranstalte in der C-Datei ist weitgehend vor der Außenwelt gekapselt.
17:20
Die Leute, die diese Bibliothek anwenden, die sehen gar nicht, ob sie das mit einem echten Eray zu tun haben, was zu Beginn reserviert worden ist, oder ob ich selbst einfach am Anfang gesagt habe, reserviere mal so und so viel Speicherstellen. Das wird nachher im zweiten Semester noch ein dickes Thema werden, Kapselung.
17:41
Mit Private und das Gegenteil, mit Public. Ich denke, das zeige ich ihr jetzt mal, was hier so passiert. Da mal einen Breakpunkt. Und dann gucken wir uns das an. Dann baue ich das Terminal.
18:00
Na, kann ich haben. Hat den Breakpunkt gesetzt in Initialize, hoffe ich, oder? Ja. Okay. Also, dem Initialize ist jetzt die Breite und die Höhe übergeben worden. Irgendwie ist kein Platz mehr auf dem Bildschirm für das echte Programm. Ich mache das doch wirklich zu.
18:21
Ist die Breite und die Höhe übergeben worden? Jetzt müssen wir jetzt gucken bei den Statics, ob er wirklich Breite und Höhe gesetzt hat. Zu viele Statics hier. Da unten. Er hat jetzt die... Na, mal ein bisschen Breite hier noch haben.
18:42
Er hat jetzt die Breite und die Höhe wirklich gesetzt. Sie sehen, wegen Statics schreibt er dahinter in der Datei robot. Sind Breite und Höhe jetzt wirklich gesetzt auf vernünftige Werte? Und Field. Field steht auf einem Zeiger. Das ist jetzt hexadezimal die Adresse, die in dem Zeiger steht.
19:03
Dafür braucht man vor allen Dingen hexadezimal Zahlen. Das Arbeiten mit den Bit-Mustern kam mir auch schon mal vor, wenn ich 8-0-hexadezimal hinschreibe, dass ich das vorderste Bit angestellt habe oder so. Aber wo die hexadezimal Zahlen am häufigsten vorkommen, ist bei Zeigern. 2a6.
19:20
Das ist der Anfang des Feldes nun. Die Funktion hier, diese systemeigene Funktion memory allocate hat mir jetzt gesagt, du willst 12 bytes haben. Okay, ich reserviere der 12 bytes. Und das ist, was er zurückgeliefert hat. Die Adresse von dem ersten dieser 12 bytes.
19:40
02a6. Da stehen nun 12 bytes, in denen ich rumvorwerken kann. Gucken wir uns mal den Speicher an. View memory. Jetzt wird es wirklich ein bisschen voll. 02a6.
20:01
02a6. Na, ein bisschen schnell hier. 02a6. Also, das wäre a0, a1, a2, a3, a4, a5, a6.
20:24
Hier würde das anfangen und dann 12 bytes. Dann greichen. Und nun fange ich an, an diese Speicherstellen Zufallszahlen zu schreiben. Das war ja das nächste, was hier passiert. Ich gehe mit einer doppelten Schorschleife rein und schreibe Zufallszahlen.
20:41
Das heißt, hier müssten jetzt eins nach dem anderen Zufallszahlen erscheinen. Jetzt müsste eigentlich der erste schreiben. Was war das? 0, 1, 2, 3, 4, 5, 6. Hier bei den Nullen müsste jetzt etwas stehen. Da, ok. Jetzt hat er die erste Zufallszahl
21:01
reingeschrieben. An die erste Adresse, dieser Pointer, diese Sternchenvariable, field sagt, wo er hinschreiben muss. Die Adresse, Hausnummer, 02a6. Da hat er das jetzt hingeschrieben. Und der Zugriff war genauso, als ob es ein Array wäre.
21:20
Sie sehen, field ist jetzt ein Pointer, aber ich kann damit so arbeiten, als ob es ein Array wäre. Ein Array, und jetzt steht hier hinten einfach 0 mal die Breite plus 0. Ein Array in eckigen Klammern 0. Das heißt, das, was da steht, wo der Pointer gerade ist. Den nächsten. Jetzt ist J1 weiter. J ist 1 weiter.
21:42
Und er nimmt jetzt Pointer und in eckigen Klammern I mal 0 plus 1. Das heißt, er schreibt in die nächste Speicherstelle rein. Da, in die nächste Speicherstelle rein. Und so weiter. Setze ich mal dahinter einen Breakpoint. Ja, das ist gut. Wie setze ich da jetzt mal einen Breakpoint?
22:02
Ich gehe mal in die Main-Funktion und setze hier den Breakpoint. Und jetzt müsste hier ja noch eine Palette an Zufallszahlen erscheinen.
22:22
Okay, das sollten vielleicht dann so ein paar Zufallszahlen sein. Sie sehen das jetzt hier. 02, 03, 01 und so weiter. Das sind meine Zufallszahlen. Natürlich jetzt nicht 12. Das Beispiel war 12. Ich hatte ja gesagt 87. Das hier ist jetzt mein zweidimensionales Feld.
22:42
Mit 56 Einträgen. Nicht 12 wie in dem Beispiel, sondern tatsächlich 56 Einträgen. Diese Zahlen hier 00. Was ist es auswendig gar nicht? Hier gehört es schon dazu. 0, 1, 2, 3, 4, 5. Die gehört noch nicht dazu. Die 02. Da fängt es an. Bei der 02 fängt es an. Und hier bei der 03 scheint es aufzuhören. Das sind die 56 Zahlen aus meinem Feld.
23:04
Die stehen natürlich nicht zweidimensional im Speicher. Sowieso nicht. Auch wenn sie ein zweidimensionales Array bauen, stehen die nicht zweidimensional im Speicher. Die stehen immer linear hintereinander im Speicher. Nur habe ich den Ärger, dass ich jetzt damit arbeiten muss, wenn ich den Speicher selbst reserviert habe. Ich muss jetzt selbst umrechnen.
23:20
Die so und so vielte Zeit, die so und so vielte Spalte. Wo steht in dieser linearen Folge jetzt das entsprechende Element. Insofern erstmal keine Angst vor Zeigern. Sie können Zeiger so verwenden, als ob es die Namen von Arrays sind. Wo bin ich hier gerade? Da bin ich.
23:41
Field ist ein Zeiger. Aber wenn Sie so schreiben, fällt es Ihnen gar nicht mehr auf, dass es ein Zeiger ist. Also man kann Zeiger so verwenden, wie die Namen von Arrays. Und Sie sagen dann einfach, gib mir mal den so und so vielten hinter dieser Hausnummer. Wenn Sie es so rumschreiben, umgekehrt, in den so und so vielten, hinter dieser Hausnummer, namens Field, schreibt rein,
24:00
was ich hier sage. Und, machen wir es unten bei dem Print. So ist das Print. Hier ist es genau umgekehrt. Diese Hausnummer, da hinter der so und so vielte, hol den mal raus und gib mir den zurück. Das ist das Schöne an C und C++, dass die Namen von Zeigern so verwendbar sind, wie die Namen von Arrays.
24:21
Sie können hier jetzt gar nicht sagen, ist das ein Array oder ist das Field hier ein Zeiger. Interessiert an der Stelle auch gar nicht. Es verhält sich gleich. Die Frage ist, wo es herkommt. Wenn Sie es so bauen, sagen Sie dem System, gib mir mal so und so viel Bytes, ob 12 oder ob 56 und speicher in Field, wo denn das anfängt,
24:41
was du da reserviert hast. Und was man nicht vergessen sollte, was bei den Arrays eben auch automatisch funktioniert, was man nicht vergessen sollte, ist am Ende, na, wo waren wir ja? Wenn man fertig ist, such, such, such. Wenn man fertig ist, sollte man auch noch sagen, dass man fertig ist und das wieder freigeben.