Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

12.05.2017, 13:06

Pascal: Pointer in Struct(record) gute Idee?

Hello Leute,

ich würde ganz gerne eure Hilfe in Anspruch nehmen und gerne fragen, ist das unten folgende Prinzip ok oder verstößt man quasi gegen die Konventionen der OOP wenn ich sage:

Quellcode

1
2
3
4
Test = record
  A, B, C, D: ^Int32; readonly; //keine Arrays
  Bla: Array of Byte; readonly;
end;


Oder sollte ich wenn ich so eine Codestück habe, doch leider aus, in dem Fall "Test" eine Klasse machen?

Was Sagt ihr?

Mfg

ProgFrog

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

2

12.05.2017, 13:16

Ich kenne mich mit Pascal nicht wirklich aus. Wenn du deinen Code etwas beschreiben würdest kann ich vielleicht trotzdem meinen Senf dazu geben. Was ein record ist kann ich noch fix ergooglen aber den Rest hätte ich gern kurz erläutert. Was soll das ^ ? Oder geht es gar nicht um den Inhalt sondern darum dass du ein record anstatt einer Klasse nutzt?

edit: Kannst du in einem record nur Datenmember hinterlegen oder können da auch Funktionen rein? Falls nein würde ich fragen welchen Vorteil record, bzw welchen nachteil class bietet? Hat record keinen Vorteil gegenüber class würde ich class verwenden. Warum auch nicht?
Ansonsten würde ich mich nicht zu sehr auf OO versteifen. OO ist ein Konzept was dir bei deiner Arbeit helfen soll. Das bedeutet meiner Meinung nach aber nicht dass du alles bis zum Ende nach OO Prinzipien durchdesignen musst. Das ganze sollte Mittel zum Zweck sein. Am besten lernt man meiner Meinung nach wenn man mit etwas auf die Nase fällt und dabei sieht wie es besser geht. Dann hast du nämlich direkt verinnerlicht warum es so besser geht. Von daher probier ruhig mal ein wenig rum und teste auch andere und neue Wege aus.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Schorsch« (12.05.2017, 13:23)


3

12.05.2017, 13:41

Ok erstmal vielen Dank für die schnelle Antwort!

1)^ --> ist ein Zeiger :) und @ --> gib mir die Adresse von...


2)Das Datenstrukturmodell ist eig. ziemlich ähnlich zu C++:
record --> Wird auf dem Stack erstellt und bei Zuweisungen an record des gleichen Typs wird eine neue Kopie erstellt
class --> Wird auf dem Heap erstellt und bei Zuweisungen an class des gleichen Typs wird eine Adresse an das bestehende Objekt kopiert, also 2 zeiger auf ein Objekt erstellt
Object --> Wird auf dem Stack erstellt, kann aber ALLES was eine Klasse kann und bei Zuweisung des gleichen Typs, wird auch hier eine Kopie erstellt, unterschied zwischen Record und Object liegen nur in der Designmächtigkeit, sprich Vererbung, virtuelle Funktionen usw...

Also ich habe einen Anwenderfall, dass ich intern einen sog. Chunkbuffer habe und der hat aus performance-gründen, nur Zeiger auf schon vorhanden übergebene Primitive Variablen , soll heißen, ich will nicht, dass die Variablen jedesmal kopiert werden, wenn ich einen neuen Chunkbuffer erstelle:

Etwas Code:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ChunkBuffer = record            
  public    
    property Amount:         ^Count;     readonly; 
    property Current:        ^Position;  readonly;
    property Space:          ^ChunkSize; readonly;    
    property Data:           array of Byte; readonly; 
  
    constructor(const fixSize: ^ChunkSize; 
                const pos: ^Position;
                const countBytes: ^Count);
    begin   
      Data := new array of Byte(fixSize^);
      Space := fixSize;  
      
      var offset := new SafeChunkOffset(direction, fixSize, pos);  //nicht relevant für Frage^^
      var &current := new SafeChunkPosition(@offset, countBytes);  //nicht relevant für Frage^^
      Amount := new SafeChunkCount(fixSize, @&current, countBytes).Value;//nicht relevant für Frage^^
      Current := @&current.Value;  
    end;


Ich will nur Speicher sparen, in dem ich nicht jedesmal das gleiche von vorne neu übergeben muss und immer wieder neue Kopien von den Parametern übergeben werden, wenn ich das gleiche Ding, 5mal wieder brauche, war zumin. mein Gedanke dahinter und meine Frage nun war, ist das so eine gute Entscheidung von mir, diesen Buffer, der eine Struktur(Stackspeicher) ist, mit Adressen auf andere Stackvariablen zu befüllen, also das er NUR Pointer hat und keine wirklichen Daten selber speichert.

Ich hoffe ihr versteht was ich meine^^

Edit:
Ja, C++ alloziert alles auf dem Stack, aber bis auf das class in Pascal auf dem heap alloziert wird, ähnelt sich das Object-Model doch recht gut.

Edit:
Hier die Struktur, die Chunkbuffer braucht.

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ByteChunk = public record   
  private
    fIsFull: Boolean;      
    fCache: ChunkBuffer; {ON STACK}

    {the record works internally just with this adress!}
    fCacheAdr: ^ChunkBuffer;
  public 
    property RW_Size:     BinaryStep read BinaryStep(fCacheAdr^.Amount^);
    property Space:       ChunkSize read fCacheAdr^.Space^;
    property Current:     Position read fCacheAdr^.Current^;

    constructor(const aSpace: ChunkSize; const start: Position;
                const binAmount: BinaryStep);
    begin 
      fIsFull := false;
      fCache := new ChunkBuffer(@aSpace, @start, @Int64(binAmount));
      fCacheAdr := @fCache;       
    end;

Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »ProgFrog« (12.05.2017, 14:50)


Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

4

12.05.2017, 14:49

Ja, C++ alloziert alles auf dem Stack, aber bis auf das class in Pascal auf dem heap alloziert wird, ähnelt sich das Object-Model doch recht gut.

Bei C# werden Klassen auf dem Heap und Strukturen auf dem Stack erstellt. Aber darum soll es hier ja nicht gehen :)

So 100% folgen kann ich dir grad nicht. Angefangen mit den Zeigern. Sind die primitiven Typen größer als die Zeiger? Falls ja, speichert dein Ansatz vermutlich speicher. Ich würde das aber vielleicht mal profilen. Zusätzlich, ist deine Anwendung wirklich so Speicherkritisch? Normal würde ich sagen solltest du den Ansatz wählen der ohne Optimierungsgründe am sinnvollsten für dich ist. Wenn es begründet zu Problemen führt würde ich anfangen zu optimieren. Compiler optimieren selbst eine Menge und da wäre ich teilweise Vorsichtig mit einfachen Annahmen. Also würde ich vielleicht mal mit einem Profiler gucken ob und wo es zu Problemen kommt.
Was dann deine Frage angeht, kannst du das nicht einfach mal beides testen und dann gucken was mehr Speicher verbraucht? Dann wärst du zumindest auf der sicheren Seite.

Zwar OT, aber wie kommst du zu Pascal :) Jedem das seine aber die Gründe würden mich einfach interessieren. Die Sprache sieht man ja recht selten.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

5

12.05.2017, 15:39

Ok, ich werde das mal Profilen, aber ja, der Gedanke war wirklich nur, dass nicht unnötig immer neue Kopien erstellt werden, denn ich brauche diesen ByteChunk in einem Array und das wäre dann eine Speicherechnung von:

chunks.Length * 48(Alle bislang gezählten Kopien von "Call-by-Value") auf 32bit OS: Obwohl es nur benötigt:

chunks.Length * 48/2 (weil Pointer nur die hälfte des Speichers meiner 8byte Datentypen verbrauchen.


Und zu meiner Wahl auf Pascal:
Ich finde die Sprache und die Möglichkeiten einfach saugeil, wie ihr C++ super findet^^

Und ich respektiere jedem das seine natürlich, nur ich fühle mich mit den Möglichkeiten und der Syntax bei Pascal einfach super wohl :thumbup:

6

12.05.2017, 15:48

Pascal: Pointer in Struct(record) gute Idee?

Und wo ich mir halt auch nicht so sicher bin ist, mein ByteChunk hat eine Funktion: ChangeCache(ByteChunk* newChunk)

Wenn ich jetzt den internen Puffer des 1.Chunks auf einen anderen Puffer zeigen lassen möchte, dann weise ich den zeiger von :newChunk an dem aktuellen byteChunk zu, sodass beide auf den gleichen Cache zeigen sollen und auch beide von diesen lesen/schreiben dürfen, was aber per Default nicht möglich sein soll, sondern halt nur wenn man es explicit wünscht.

Und meine Frage ist nun, ist das korrekt, dass sich die Properties der ByteChunk-struktur in Abhängigkeit des verwiesenen Caches ändern dürfen? Also wie ihr sehen könnt, steht da:

Quellcode

1
property Amount: Count read fCache^.Amount^   //heisst: Die "Amount" ist abhängig von dem, auf welchen "Amount" der aktuelle fCache zeigt


Hättet ihr das anders gemacht? oder kann man das so lassen?
:) Danke im Voraus !

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »ProgFrog« (12.05.2017, 16:02)


@zimmer

Alter Hase

Beiträge: 1 135

Wohnort: NRW Germany

  • Private Nachricht senden

7

12.05.2017, 16:25

ich arbeite auch mit algemeinen datentypen(oder wie man das jetzt bei mir nennen soll).
meist mache ich das bei neuen sachen um zu gucken ob es überhaupt funktioniert oder ob ich nicht irgendwelche sachen nicht im kopf hatte.
Ok ich mache schon ab und an auch ein konzept auf dem Papier damit sowas nicht passeirt, aber eigentlich weiß ich nie was es nötig ist :D

wenn es aus Preformans Sicht besser werden muß und ich schon glaube dass, es theoretisch geht, dann erstelle ich spezielle datentypen, das können sogar ganze arrays werden und das geht weiter bis zu den funktionen.

übrigens toll dass, Du einwenig pascal zeigst, einbishen abwechselung :D habe auch gleich die turbo pascal games gecheckt, irgendwie mag ich die:D

8

13.05.2017, 09:29

Achso und @Schorsch

Ich meinte aber C++ und da wird per Default alles erstmal auf dem Stack alloziiert :)

Wenn man eine Struktur oder Klasse auf dem Heap erstellen will, dann reserviert man es über "new" und speichert ja den zurückgegebenen Pointer in einem Struktur/Klassen - Pointer ab.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

9

13.05.2017, 13:00

Ich meinte aber C++ und da wird per Default alles erstmal auf dem Stack alloziiert

Wenn man eine Struktur oder Klasse auf dem Heap erstellen will, dann reserviert man es über "new" und speichert ja den zurückgegebenen Pointer in einem Struktur/Klassen - Pointer ab.

Genau. Und du hast ja davon gesprochen dass bei Pascal eine Klasse automatisch auf dem Heap erstellt wird. Und das ist das Prinzip welches C# verfolgt.
Was deine Frage zu den Properties angeht, an sich sieht das doch ganz vernünftig aus. Wenn eine Klasse etwas nicht selbst lösen kann, aber etwas besitzt was es lösen kann dann spricht ja nichts dagegen das einfach weiter zu leiten. Ich wüsste zumindest nicht was dagegen sprechen sollte :)
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

10

13.05.2017, 14:51

Achso meintest Du das^^

Und danke für Deine Stellungnahme bezüglich meiner "Architektur", ich brauchte da etwas Feedback von Profis :P ob das so in etwa designbar ist und ich merke auch in der Benutzung meiner Strukturen dass sie konsistent sind, weil wenn sie von der Benutzung schon sehr un-semantisch und inkonsistent sind, dann merke ich das immer dann nämlich, wenn es irgendwie sehr umständlich wird, die Datenstrukturen zu benutzen.

Werbeanzeige