Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Wie funktioniert SizeOf() intern? (https://www.delphipraxis.net/53347-wie-funktioniert-sizeof-intern.html)

SebE 14. Sep 2005 15:58


Wie funktioniert SizeOf() intern?
 
Hallo Leute,
wisst ihr, wie man die Größe einer Variable, Konstante oder eines Types herausfindet.

Natürlich: Es gibt SizeOf().

Aber wie funktioniert diese Funktion?
Wird vor einem Speicherbereich etwa immer die Länge/Größe des belegten Speichers angelegt?

Danke für Aufklärung

Dax 14. Sep 2005 16:00

Re: Wie funktioniert SizeOf() intern?
 
Das ist Compiler Magic. SizeOf(Integer) wird automatisch durch eine Konstate mit dem Wert 4 ersetzt. Bei SizeOf(Byte) wäre die Konstante 1. Das einzige, bei dem vor den eigentlichen Daten die Länge und Elementgröße gespeichert wird, sind dynamische Arrays (und auch strings, aber der Unterschied ist nicht besonders groß).

Luckie 14. Sep 2005 16:14

Re: Wie funktioniert SizeOf() intern?
 
Zitat:

Zitat von Dax
Das ist Compiler Magic. SizeOf(Integer) wird automatisch durch eine Konstate mit dem Wert 4 ersetzt. Bei SizeOf(Byte) wäre die Konstante 1.

Und wie funktioniert dann
Delphi-Quellcode:
sizeof(TMyRecord);
;)

Hansa 14. Sep 2005 16:25

Re: Wie funktioniert SizeOf() intern?
 
Mann, Luckie ! :mrgreen: Ein Record ist die Addition der zugrundeliegenden Datentypen und deren Größe steht fest ! Ein Array davon wäre dann noch eine Multiplikation der Größe der Records. Nix Compiler Magic. 8)

Luckie 14. Sep 2005 16:53

Re: Wie funktioniert SizeOf() intern?
 
Darauf wollte ich hinaus. ;) Bleibe mich zu klären, wie die Direktive packed dann brücksichtigt wird.

tommie-lie 14. Sep 2005 16:56

Re: Wie funktioniert SizeOf() intern?
 
Zitat:

Zitat von Hansa
Nix Compiler Magic.

Das, was du beschrieben hast, ist ausnahmsweise mal richtig, und genau das ist Compiler Magic :roll:
Schade drum, wäre echt eine Rarität gewesen.
Wobei nur noch zu erwähnen wäre, daß bei Records zusätzlich noch das Alignment vom Compiler beachtet wird.

shmia 14. Sep 2005 17:27

Re: Wie funktioniert SizeOf() intern?
 
Man kann ja SizeOf() auf Datentypen, Konstanten oder Variablen anwenden.

So muss es wohl ablaufen
Der Compiler schaut also in seinen Syntaxtree (die Dinge sind intern als Baum organisiert) nach.
Der Baum wird auch als "dekorierter Syntaxbaum" bezeichnet.

Trifft er auf eine Variable, dann entnimmt er den Datentyp.
Mit dem Datentyp schaut er in seinen Datatree und entnimmt die Grösse in Bytes.
Pseudocode:
Delphi-Quellcode:
function SizeOf(arg : string):integer;
begin
   item := LookupTree(arg);
   if item=nil then
      CompilerError;

   if IsVariable(item) then
      result := SizeOf(Item.datatypeName)
   else
      result := Item.Instancesize;
end;
Bei komplexen Datentypen wie Records und Objekten, liefert Instancesize die Summe der Einzelteile.
Bei Unions wird die max. InstanceSize der Einzelteile geliefert.

Hansa 14. Sep 2005 17:37

Re: Wie funktioniert SizeOf() intern?
 
Jo, shmia, so sehe ich das auch. Und das packed wird wohl vordergründig Speicherplatz sparen, aber gleichzeitig einen erhöhten Verwaltungsaufwand für den Deklarations-Baum bedeuten (=lahmer). Habe noch nie packed gebraucht.

Zitat:

Zitat von tommie-lie
daß bei Records zusätzlich noch das Alignment vom Compiler beachtet wird.

Ähh, wer so mit englischen Wörtern um sich schmeißt, der soll sie bitte mal erklären. Allerdings nicht mit neuen Pseudo-Fachbegriffen. Compiler-Alignment. :shock:

tommie-lie 14. Sep 2005 18:04

Re: Wie funktioniert SizeOf() intern?
 
Zitat:

Zitat von Hansa
Und das packed wird wohl [...] gleichzeitig einen erhöhten Verwaltungsaufwand für den Deklarations-Baum bedeuten.

Für den Deklarationsbaum selbst wird es wohl keinen Unterschied machen, ich denke mal der Compiler bastelt sich erst seine Typen und Strukturen zusammen. Aber zur Laufzeit ist es ein erhöhter Aufwand beim Zugriff auf einzelne Elemente, weil eben das Alignment fhelt und die richtigen Bits aus dem Speicher gepult und zusammengesetzt werden müssen.

Zitat:

Zitat von Hansa
Habe noch nie packed gebraucht.

Dann hast du wohl noch nie von C oder anderen Sprachen auf Records in Delphi-Code zugegriffen, dort braucht man es nämlich zum Beispiel. Daher sollten auch alle Records, die man an API-Funktionen schickt, auch als packed deklariert sein, wenn man sich die API-Funktionen selbst importiert.

Zitat:

Zitat von Hansa
Ähh, wer so mit englischen Wörtern um sich schmeißt, der soll sie bitte mal erklären. Allerdings nicht mit neuen Pseudo-Fachbegriffen.

Das ist kein Pseudo-Fachbegriff, sondern ein Defakto-Fachbegriff. Eine Suche in deiner Online-Hilfe (mindestens bei Delphi <= 7, die von Delphi2005 kenne ich nicht, habe aber nur schlechtes über sie gehört :mrgreen:) hätte dir verraten, was Alignment ist, ebenso wie ein Blick in die Kontexthilfe des Projekteigenschaften-Dialogs, wo du das Alignment einstellen kannst.
Und weil ich jetzt zu faul bin, extra Windows zu booten nur um dir etwas aus der Windows-Hilfe abzutippen, überlasse ich dem werten Leser diese Aufgabe als kleine Übung.

alzaimar 14. Sep 2005 18:55

Re: Wie funktioniert SizeOf() intern?
 
Beim Packed Record wird der Record, sofern möglich gepackt. Im Gegensatz zu ANSI bzw. UCSD-Pascal aber nur auf Byte-Ebene.
Delphi-Quellcode:
Type
  TNibble = 0..15;
  T1 = Record
    a, c : TNibble;
    b : Integer;
    End;
  T2 = Packed Record
    a, c : TNibble;
    b : Integer;
    End;
SizeOf (T2) liefert Delphi 6, bei UCSD-Pascall jedoch 3 (0,5 bytes für a und c und 2 bytes für b, integer ist/war 16 bit). Auf diese Weise hat man früher Bitsets und Statusbytes implementiert. Es war nicht definiert, das eine Menge als Bitset implementiert ist, aber die Packed Records wurden von N.Wirth eindeutig definiert. Aus Gründen der Performance ist man dann davon abgekommen, was eigentlich Schade ist.

Beim SizeOf (TSomeRecord) werden nicht die Größen der einzelnen Record-Elemente addiert, sondern wirklich die Größe des Records, die dieser im Speicher verbraucht, angegeben. So, wie es sein soll. Der Compiler erzeugt beim Parsen der Typdefinition die Offsets der Record-Elemente. Die Recordgröße ergibt sich dann zwangsläufig aus dem höchsten Offset + SizeOf (ThisElement), Auf 1 bzw. 4 Bytes aufgerunden, je nach "Packed" und Compiler-Einstellungen.

Auch wird kein "DataTree" zum Ermitteln der Speichergröße verwendet, sondern eine simple Lookupliste. Dort stehen einfach die Variablen und deren Datentyp drin. Der Compiler muss ja wissen, ob eine Variable deklariert ist, und welcher Datentyp das ist. Im Prinzip stimmt das aber Alles, was dazu erwähnt wurde...

Das ist nur als Anmerkung zu Tommie-Lie's Post gedacht...


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:07 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz