Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Integer-Datentypen - DH empfiehlt immer Integer oder Cardina (https://www.delphipraxis.net/113218-integer-datentypen-dh-empfiehlt-immer-integer-oder-cardina.html)

christian_r 4. Mai 2008 19:55


Integer-Datentypen - DH empfiehlt immer Integer oder Cardina
 
Eine Antwort auf diese Frage wollte ich schon immer mal wissen.

Zitat:

Zitat von Delphi Help
The generic integer types are Integer and Cardinal; use these whenever possible, since they result in the best performance for the underlying CPU and operating system.

Übersetzt ...
Zitat:

Zitat von Delphi Hilfe
Die Typen Interger und Cardinal sind genereische Typen. Diese sollten wann immer möglich verwendet werden, da sie die beste Performance für die zugrundeliegende CPU und das Betriebssystem gewährleisten.

Naja, wozu sind dann konkret die fundamentalen Datentypen implementiert - doch sicher nicht nur aus Gründen der Abwärtskompatibilität?

mkinzler 4. Mai 2008 20:00

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
In einer 32(64 im 32er Modus)Bit-CPU belegen auch kleinere Integer-Typen 32Bit (wenn nicht Teil einer Packed-Struktur) deshalb kann man auch gleich Cardinal nehmen

christian_r 4. Mai 2008 20:07

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Was bedeutet, das die DelphiEngine den Rest drumherum, (z.B. Byte: 255 + 1 = 0, Size( Byte ) = 1) durch entsprechende Codes nur emuliert, und das macht den fundamentalen Typ langsam?

mkinzler 4. Mai 2008 20:11

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Nein. Delphi behandelt Byte als Byte.

christian_r 4. Mai 2008 20:31

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Dann verstehe ich Deinen Beitrag #2 nicht. Kannst Du mir das bitte etwas näher erläutern? Google spuckt mir leider massenweise unbrauchbare Ergebnisse zu "delphi fundamentale typen" aus.

Ich möchte es gern verstehen, um es besser anwenden zu können.

mkinzler 4. Mai 2008 20:36

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Das macht nicht der Compiler sondern der Prozessor.

Christian Seehase 4. Mai 2008 20:38

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Moin Christian,

integer und cardinal sind die generischen Typen, dass heisst:
Bei einem 32-Bit-Compiler sind sie 32-Bit breit, bei einem 64-Bit-Compiler sind sie 64-Bit breit, ohne dass man den Code anpassen müsste.
Wenn Du, z.b., LongInt verwendest, ist er auch bei einem 32-Bit-Compiler 32-Bit breit.

christian_r 4. Mai 2008 20:49

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Moin Christian,

Zitat:

Zitat von Christian Seehase
dass heisst:
Bei einem 32-Bit-Compiler sind sie 32-Bit breit, bei einem 64-Bit-Compiler sind sie 64-Bit breit, ohne dass man den Code anpassen müsste.
Wenn Du, z.b., LongInt verwendest, ist er auch bei einem 32-Bit-Compiler 32-Bit breit.

Wolltest Du evtl. sagen, der fundamentale ist bei einem 64-Bit-Compiler trotz allem 32 Bit breit?

jbg 4. Mai 2008 21:03

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Zitat:

Zitat von Christian Seehase
Bei einem 32-Bit-Compiler sind sie 32-Bit breit, bei einem 64-Bit-Compiler sind sie 64-Bit breit

Das kommt auf das verwendete Model an. Bei C++ wird z.B. das 64:32 Model benutzt. Dort ist "int" und "unsigned int" in der 64Bit Version auch nur 32 Bit breit. Welches Model CodeGear verfolgt, werden wir wohl erst nächstes Jahr (aktualisierte RoadMap) erfahren.

christian_r 4. Mai 2008 21:28

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Ich bin immer noch nicht wirklich schlauer als vorher. :? Verdammt, ich will's wissen! :gruebel:

Muetze1 4. Mai 2008 22:04

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Zitat:

Zitat von mkinzler
Das macht nicht der Compiler sondern der Prozessor.

Nein. Der Compiler hält soviel Space vor durch den erzeugten Code und beachtet bei SizeOf() immernoch den eigentlichen Typ.

@christian_r:
Der Compiler führt ein Alignment durch bei der Generierung deines Codes, damit der Prozessor dort nicht extra arbeiten muss. Wenn du eine Variable als Byte definierst, dann hält er 32 Bit vor (32 Bit Compiler), nutzt aber nur ein Byte davon. Dadurch kann der Prozessor immer 32 Bit beim Lesezugriff holen bzw. Schreiben. Der vom Compiler generierte Code wiederrum achtet aber darauf, nur die von dir definierten 8 Bit zu nutzen.

Hintergrund:
Wenn der Compiler einen echten 8 Byte nehmen sollte und du diesen liest, liest die CPU trotzdem immer einen Wert, der so gross ist wie sein Datenbus ist, ein. Dies ist die kleinste Einheit, die er bei einer Anfrage an den RAM stellen kann, da dieser auch einen solch breiten Datenbus hat. Er hat also beim Lesezugriff auf die adressierte RAM Stelle immer den gesamten Datenbus mit den Daten belegt. Wenn nun der Prozessor nur 8 Bit haben will (1 Byte), dann gehen über den Datenbus trotzdem 32 Bit rüber, gehen durch den Cache, etc. und die CPU schmeisst nachher 24 Bit von den eingelesenen Werten weg, da es nur 8 Bit braucht. Dies ist ein extra Aufwand von der CPU.

Wenn alle Datentypen versuchen eine durch die Breite des Datenbusses teilbare Grösse zu haben, dann kann der Prozessor optimal arbeiten. Wenn du z.B. einen Record mit einen Word und einen Integer nacheinander definierst, dann werden beide an einer durch 4 teilbaren Adresse angelegt. Der Record wird 16 Byte gross sein, was optimal für die CPU ist, aber nachteilig, wenn du z.b. eine Datei einlesen willst, der diese Struktur enthält, weil dort das Word nur 16 Bit gross sein soll. Dafür kannst du dann das "packed" Schlüsselwort verwenden. Damit schaltest du das Aligment ab und alle Werte liegen in ihrer definierten Grösse nacheinander im Speicher. Damit kommt es aber auch dazu, dass der Integer auf einer nur durch 2 teilbaren Adresse liegt. Da der Datenbus aber 32 Bit gross ist, muss die CPU, um diesen Integerwert zu lesen, zweimal lesen. Einmal adressiert er die Adresse mit den oberen 16 Bit des integers und liest diese ein. Am Datenbus liegen dann oben 16 Bit das Word an und in den unteren 16 Bit die oberen 16 Bit des Integers an. Diese holt sich die CPU raus und merkt sich diese um danach die darauffolgende Adresse (4 Bytes weiter) zu lesen. In diesen findet er in den oberen 16 Bit (der 32 Bits die am Datenbus anliegen) die für den Integer unteren 16 Bits. Diese setzt er zusammen und erhält nun endlich deinen Integer den du wolltest. Aber er musste zweimal lesen um diesen zu erhalten.

Grundlegend sollte das Problem nun verständlich sein. Es ist immer zu versuchen die Daten an aligned Adressen abzulegen und das versucht der Compiler von Haus aus. Ungerade Adressen sind ein graus für die CPU, weil er zweimalig lesen muss. Heutzutage sorgen Sprungvorhersage, Adressvorhersage und Cache pre filling dafür, dass nebenbei die CPU ermittelt, wo der Code ein paar Opcodes später hinspringt, was er als nächstes adressiert bzw. lesen will, um diese Aktionen schon vorher zu erledigen. Da wird dann mal schon ein paar Opcodes zuvor eine Adresse vom Hauptspeicher ausgelesen, die erst später vom Code adressiert wird. Auch wird vorhergesagt, wohin bestimmte Verzweigungen gehen, um im Idealfall den Code schon in den Cache geladen zu haben, etc. Im besten Falle fallen WaitStates weg (Wartezyklen die die CPU einlegt zwischen Adressierung und Freigabe des Datenbusses) und der Cache hält fast alle Daten vor und im schlimmsten Falle war die Vorhersage falsch und alle Daten müssen besorgt werden und der gesamte Cache enthält falsche Daten und muss geleert werden. All diese Bemühungen der CPU und dieser kleiner Helferleins kann man sich gut in CPU internen Register (MSR) anschauen und auch deren Effizienz ermitteln. Mit diesen Registern und ein paar Anleitungen vom CPU Hersteller, können die Compiler optimierten Code bauen, die auch einwandfrei von diesen Helferleien unterstützt wird und deren falschen Voraussagen auf ein minimum reduzieren.

Aber egal, das war nicht mehr die Frage an sich...

3_of_8 4. Mai 2008 22:06

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Also ich vermute mal, ein Integer/Cardinal wird in einem 64-Bit-System 64 Bit groß sein.

Da ein Prozessor immer darauf optimiert ist, mit Zahlentypen in seiner Wortbreite zu arbeiten, sollte man also Integer/Cardinal verwenden, da diese ja gerade immer in Wortbreite sind. (Wenn CodeGear sinnvoll handelt)

Die anderen Datentypen mit fester Größe sind vor allem dann wichtig, wenn die Größe wichtig ist. Das kann bei DLL-Aufrufen so sein, oder wenn man irgendwas per Netzwerk verschickt oder auch in eine Datei speichert. Wenn man da z.B. statt LongWord einfach Cardinal schreibt und das Programm dann mit einem 64 Bit-Delphi kompiliert, kracht das natürlich, wenn man eine Datei von der 32 Bit-Version einliest.

Also: Wenn die Größe wichtig ist, sollte man die Typen ShortInt/Byte, SmallInt/Word, LongInt/LongWord verwenden, ansonsten Integer/Cardinal.

christian_r 4. Mai 2008 22:11

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
@Muetze1

Wow. Danke! :thumb:

Die ersten zwei Abschnitte hab ich gelesen. Aber ich werde mir das morgen noch einmal in Ruhe beim Frühstück zu Gemüte führen.


Vielen Dank an alle für Eure Bemühungen.
Gute Nacht.

christian_r 4. Mai 2008 22:16

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Zitat:

Zitat von 3_of_8
Also ich vermute mal, ein Integer/Cardinal wird in einem 64-Bit-System 64 Bit groß sein.

Da ein Prozessor immer darauf optimiert ist, mit Zahlentypen in seiner Wortbreite zu arbeiten, sollte man also Integer/Cardinal verwenden, da diese ja gerade immer in Wortbreite sind. (Wenn CodeGear sinnvoll handelt)

Das beantwortet meine Frage aus Beitrag #8

Zitat:

Zitat von christian_r

Zitat:

Zitat von Christian Seehase
Bei einem 32-Bit-Compiler sind sie 32-Bit breit, bei einem 64-Bit-Compiler sind sie 64-Bit breit, ohne dass man den Code anpassen müsste.
Wenn Du, z.b., LongInt verwendest, ist er auch bei einem 32-Bit-Compiler 32-Bit breit.

Wolltest Du evtl. sagen, der fundamentale ist bei einem 64-Bit-Compiler trotz allem 32 Bit breit?

War dann wohl doch nur ein Tip-Fehler.

Also noch mal Danke an alle.

jbg 4. Mai 2008 22:23

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Zitat:

Zitat von 3_of_8
Wenn CodeGear sinnvoll handelt

Microsoft hat dann also bei MSVC und beim .NET nicht sinvoll gehandelt?
Ich glaube doch eher, dass CodeGear Micorosofts Beispiel folgt, da sie für deren Betriebssystem Code erzeugen. Und es wäre doch schon etwas dumm, wenn ein C++ "int" nicht dem Delphi "Integer" entspräche.

3_of_8 4. Mai 2008 22:54

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Welchen Sinn hätte es sonst, dass es einerseits ein LongWord und einen Cardinal gibt? Ich meine, wenn ich eine portierbare Anwendung schreiben will, dann ist es nützlich, einen Zahlendatentypen zu haben, der Wortbreite hat.

Und dass ein Integer nicht das gleiche ist wie ein int, naja, was ist so schlimm daran? Ein String in Delphi ist auch kein String in C und ein Byte/Char in Delphi muss (gemäß Standard) auch nicht unbedingt ein char in C sein. Sogar bei Booleans gibt man ja in Delphi, wenn man eine DLL importiert, nicht "Boolean" an, sondern "LongBool".

Ich würde es für sehr sinnvoll halten, wenn es weiterhin so bleibt: Es gibt zwei ordinale Datentypen, die immer Wortbreite haben, jeweils einer vorzeichenbehaftet und einer nicht und dann je zwei ordinale Datentypen für jede Zweierpotenz von Bytes darunter.

Dax 4. Mai 2008 23:07

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Aber sehr wahrscheinlich benutzt jede Anwendung, die Daten in Dateien ablegt, für Vierbytezahle Cardinal oder Integer statt Longint und Longword. All diese Programme würden dadurch schwerer portierbar (solche Fehler zu finden ist schwer...).

Medium 4. Mai 2008 23:18

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Was wiederum völlig egal ist, solange diese älteren Programme nicht mit einem neueren Compiler übersetzt werden, der die neue Wortbreite zu Grunde legt. Bestehende Executables und DLLs sind also genausowenig davon betroffen, wie Übersetzungen mit 32 Bit Compilern, womit die Menge des Codes der dahingehend geändert werden müsste ganz erheblich schrumpft. Ich bin durchaus der Meinung, dass man diesen Umstand sehr wohl einer einheitlichen und eindeutigen Nomenklatur dulden kann. Im zweifel rauscht man einfach durch den alten Code, und ersetzt alle Integer-Deklarationen durch LongInt, und hat wieder das alte Verhalten mit quasi null Aufwand. Die durch die inkonsequente Namensgebung entstehenden Missverständnisse stehen dazu imho in keinem Verhältnis. Ich seh ja schon die Foren überquellen :lol:
Und wo dann dennoch Speed gefragt ist, was Deklarationsabhägig nicht so häufig der Fall sein dürfte, ist es imho auch nicht zu viel verlangt die paar Schleifenvariablen o.ä. von Hand auf den wortbreiten Typ zu ändern, nachdem man den restlichen Code per Suchen und Ersetzen angepasst hat.

Aber eine Bezeichnung von ehemals generischen Typen auf eine feste Länge zu setzen, halte ich schon allein aus irgenwie ästhetischen Grunden für... mh, mistig :)

3_of_8 4. Mai 2008 23:25

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
@Dax: Das sollte eigentlich nicht so sein, dass Integer und Cardinal generisch sind, ist schließlich weithin bekannt. Wenn also ein Programm für solche Zwecke diese Typen nutzt, würde ich einfach behaupten, es ist schlecht geschrieben.

Muetze1 4. Mai 2008 23:47

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Zitat:

Zitat von Dax
Aber sehr wahrscheinlich benutzt jede Anwendung, die Daten in Dateien ablegt, für Vierbytezahle Cardinal oder Integer statt Longint und Longword. All diese Programme würden dadurch schwerer portierbar (solche Fehler zu finden ist schwer...).

Aber das wurde schon immer so gehandhabt. Die generischen Typen wachsen mit und somit sind alle Strukturdefinitionen, welche irgendwie das Programm verlassen, damit definiert worden, damit sie gleich gross bleiben, egal auf welchem Compiler. Dies habe ich schon immer so angewendet, da es schon immer so dokumentiert war. Wenn dies nicht beachtet wurde (was leider recht häufig der Fall war), dann muss man sich wirklich nicht wundern. Das ist dann selbstverschuldeter Aufwand.

christian_r 5. Mai 2008 01:29

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Zitat:

Zitat von Muetze1
Die generischen Typen wachsen mit und somit sind alle Strukturdefinitionen, welche irgendwie das Programm verlassen, damit definiert worden, damit sie gleich gross bleiben, egal auf welchem Compiler.

Das bedeutet also, wenn man programmintern fundamentale Typen verwender, ist es egal, sogar angebracht. Aber wenn man "das Programm verlässt", z. B. bei API-orientierten Anwendungen, sollte man die generischen Typen verwenden, da diese sich dem zugrundeliegenden Betriebssystem und der CPU anpassen, demzufolge auch der API zugrunde liegen.

[edit]
Ich bleibe mal beim API-Beispiel.
Wenn ich auf einem 32 Bit Betriebssystem einen API-Aufruf mit einem Ordinalwert starte, dann ist der zugrundeliegende Datentyp auch 32Bit und bei einem 64 Bit Betriebssystem würde er automatisch ebenfalls 64 Bit Länge erhalten. Somit wäre es ungünstig, einen Longint zum Emfpang eines Rückgabewertes einer API-Funktion zu verwenden, welche einen ordinalen Wert zurückliefert. Denn in einem 64-Bit-System wäre der Rückgabewert für den Longint schon nicht mehr speicherbar, bzw. nur über Umwege zu verarbeiten. Und das wäre dann die veringerung der Performance, wie es in der DH schon beschrieben wurde.

Verwende ich generische Typen, kann ich die Anwendung auf verschiednen XXX-Bit-System laufen lassen ohne Probleme mit der Speicherung der Werte zu haben.
[/edit]

Richtig verstanden?

Medium 5. Mai 2008 03:00

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Leider ist die Welt nicht ganz so schön. Wie breit ein generischer Typ ist, wird vom Compiler festgelegt, und zwar zur Compiletime. Das heisst, du kannst das beschriebene Verhalten nicht von ein und der selben Executable erwarten, sondern musst schon noch die Quelle mit einem jeweiligen Compiler übersetzen. Der Gewinn der daraus entstünde wäre, dass du im Code nichts anzupassen bräuchtest. (Und man müsste voraussetzen können, dass die API auch in vollem Umfang mit "wächst".)

Die Kommunikation mit einer API ist aber eigentlich nicht der Grund weswegen man generische Typen empfiehlt. Da geht es in der Tat eher um das schon beschriebene Alignment, und um zu durchschauen warum das genau ein Vorteil ist, ist etwas Lektüre zu CPU-Architektur bzw. Datenbussen und Pipelines nicht übel. Einfach gesagt ist man damit "netter" zur CPU, und wird durch höhere Geschwindigkeit belohnt. In den meisten Anwendungen dürfte der Unterschied vermutlich nicht gravierend auffallen, aber manchmal kommt es halt auf jeden Cycle an, den man so einfach gewinnen kann.

christian_r 5. Mai 2008 03:17

Re: Integer-Datentypen - DH empfiehlt immer Integer oder Car
 
Zitat:

Zitat von Medium
Wie breit ein generischer Typ ist, wird vom Compiler festgelegt, und zwar zur Compiletime. Das heisst, du kannst das beschriebene Verhalten nicht von ein und der selben Executable erwarten, sondern musst schon noch die Quelle mit einem jeweiligen Compiler übersetzen. Der Gewinn der daraus entstünde wäre, dass du im Code nichts anzupassen bräuchtest.

OK, das habe ich klar verstanden.

Zitat:

Zitat von Medium
Die Kommunikation mit einer API ist aber eigentlich nicht der Grund weswegen man generische Typen empfiehlt.

War nur ein Anwendungsbeispiel, welches ich vermutet habe.

Zitat:

Zitat von Medium
Da geht es in der Tat eher um das schon beschriebene Alignment, und um zu durchschauen warum das genau ein Vorteil ist, ist etwas Lektüre zu CPU-Architektur bzw. Datenbussen und Pipelines nicht übel.

Ich habe zu Alignment mal Wikipedia befragt. Wikipedia :: Speicherausrichtung

Wenn mir bitte jemand ein kleineres Anwendungsszenario beschreiben möchte, ich bin dem Lernen nicht abgeneigt. Und das macht es bestimmt einfacher verstehbar.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:49 Uhr.

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