AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Algorithmen, Datenstrukturen und Klassendesign Seltsames Phänomen: Unterschied zwischen Integer und Int64

Seltsames Phänomen: Unterschied zwischen Integer und Int64

Ein Thema von hschmid67 · begonnen am 9. Jan 2021 · letzter Beitrag vom 9. Jan 2021
Antwort Antwort
hschmid67

Registriert seit: 2. Jul 2012
Ort: Weilheim i. Obb.
53 Beiträge
 
Delphi 10.4 Sydney
 
#1

Seltsames Phänomen: Unterschied zwischen Integer und Int64

  Alt 9. Jan 2021, 09:01
Hallo zusammen,

ich habe die letzten Stunden mit einem mir unverständlichen Phänomen verbracht. Es wäre schön, wenn jemand mir das erklären könnte:

Ich hab eine sehr einfache Beispielklasse mit einem Fluent-Interface. Sie soll in diesem Beispiel einfach nur ein Objekt erzeugen, eine lokale Variable (über var- oder out-Parameter) setzen und mit dieser lokalen Variablen soll dann eine Objektvariable verändert werden. Danach wird der Inhalt der Objektvariablen in einer Messagebox ausgegeben.

Delphi-Quellcode:
unit uTest;

type
  TTest = class
  private
    FInt: Int64;
  public
    function SetTo2(var mValue: Int64): TTest;
    function SetI(mValue: Int64): TTest;
    procedure WriteInt;
  end;

implementation

uses
  System.SysUtils,
  Vcl.Dialogs;

function TTest.SetTo2(var mValue: Int64): TTest;
begin
  Result := Self;
  mValue := 2;
end;

function TTest.SetI(mValue: Int64): TTest;
begin
  Result := Self;
  FInt := mValue;
end;

procedure TTest.WriteInt;
begin
  ShowMessage(FInt.ToString);
end;

end.
Wenn ich das ganze dann so aufrufe:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  lCount: Int64;
  lTest: TTest;
begin
  lTest := TTest.Create;
  try
    lTest.SetTo2(lCount).SetI(lCount + 1).WriteInt;
  finally
    lTest.Free;
  end;
end;
erhalte ich folgende Ausgabe:

Code:
18159907708203893
wobei ich ja eigentlich einfach nur eine "3" sehen wollte. Warum funktioniert das nicht??? Ach ja: Wenn ich überall statt des "Int64" ein "Integer" schreibe, dann funktioniert es wie gewollt.

Was habe ich da nicht verstanden? Ich dachte, "Int64" ist einfach die 64-Bit-Variante von einem "Integer" - und ansonsten identisch. Hängt das mit meinem verwendeten Windows10 64-Bit zusammen?

Es muss aber wohl mit dem Fluent-Interface zusammenhängen, denn so funktioniert es auch mit Int64 problemlos:

Delphi-Quellcode:
lTest.SetTo2(lCount);
lTest.SetI(lCount + 1);
lTest.WriteInt;

Herzliche Grüße
Harald
Harald

Geändert von hschmid67 ( 9. Jan 2021 um 13:01 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
39.180 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Seltsames Phänomen: Unterschied zwischen Integer und Int64

  Alt 9. Jan 2021, 13:02
Delphi-Quellcode:
lCount := 110;
lTest.SetTo2(lCount).SetI(lCount + 1).WriteInt;
Kommt hier 111 raus?

Wenn ja, dann wird der Parameter für SetI schon zu beginn der Zeile bereitgestellt (vor Aufruf von SetTo2).
Das kannst dann natürlich auch im Assembler des Compilates im Debugger sehen.



Meckert hier nicht eventuell auch der Compiler, vonwegen nicht-initialisierter Variable?
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014
  Mit Zitat antworten Zitat
ghubi01

Registriert seit: 18. Nov 2017
110 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Seltsames Phänomen: Unterschied zwischen Integer und Int64

  Alt 9. Jan 2021, 13:03
Hallo,

stell mal Zielplattform auf Windows 64 Bit. Dann funktionierts.
  Mit Zitat antworten Zitat
hschmid67

Registriert seit: 2. Jul 2012
Ort: Weilheim i. Obb.
53 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Seltsames Phänomen: Unterschied zwischen Integer und Int64

  Alt 9. Jan 2021, 13:07
@himitsu: Ja, hier kommt tatsächlich 111 raus.

@ghubi01: Hab ich noch nicht probiert, aber das wird wohl funktionieren. [EDIT]Ja, es funktioniert.[/EDIT] Die Frage ist nur: Warum funktioniert es unter 32Bit nicht?

Und vor allem: Warum funktioniert es mit "Integer"?

Vielen Dank Euch für's Mitdenken!
Harald
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
9.303 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Seltsames Phänomen: Unterschied zwischen Integer und Int64

  Alt 9. Jan 2021, 13:26
Vor geraumer Zeit hatten wir schon mal so was in der Art: In Delphi, are parameters evaluated in order when passed into a method?
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
hschmid67

Registriert seit: 2. Jul 2012
Ort: Weilheim i. Obb.
53 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Seltsames Phänomen: Unterschied zwischen Integer und Int64

  Alt 9. Jan 2021, 13:34
Hallo Herr Raabe,

vielen Dank für den Hinweis. Dann wäre ja mein korrektes Ergebnis mit "Integer" nur Zufall? Puh, nicht schön! Meine Idee war - und hier wäre das sinnvolle Beispiel dazu - ein Dataset-Objekt so zu konstruieren, dass folgendes Konstrukt möglich wäre:

Delphi-Quellcode:
CreateSpecialDataset('SELECT nr, titel FROM table')
  .RecordCount(lCount)
  .Append
  .SetInteger('nr', lCount + 1)
  .Post;
Viele Grüße
Harald
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
9.303 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Seltsames Phänomen: Unterschied zwischen Integer und Int64

  Alt 9. Jan 2021, 13:59
Obwohl ich persönlich kein Freund des Fluent-Interfaces bin, würde ich schon meinen, dass der Code so korrekt ist. Schaut man sich aber den erzeugten Assembler-Code an, wird schnell klar warum das nicht so ist. Da werden erst alle Parameter auf den Stack gelegt und dann die einzelnen Aufrufe ausgeführt. Weil der Rückgabewert ja eh schon auf dem Stack liegt, ist das eigentlich gar nicht so dumm gelöst. Faktisch wird die Fluent-Aufruf-Kette aber dann so behandelt wie ein einzelner Aufruf mit zwei Parametern - wie in dem Link beschrieben mit den entsprechenden Nebeneffekten.
Code:
Project765.dpr.44: lTest.SetTo2(lCount).SetI(lCount + 1).WriteInt;
0041D30F 8B45F8           mov eax,[ebp-$08]
0041D312 8B55FC          mov edx,[ebp-$04]
0041D315 83C001           add eax,$01
0041D318 83D200           adc edx,$00
0041D31B 52               push edx
0041D31C 50               push eax
0041D31D 8D55F8           lea edx,[ebp-$08]
0041D320 8B45F4           mov eax,[ebp-$0c]
0041D323 E800FFFFFF      call TTest.SetTo2
0041D328 E827FFFFFF      call TTest.SetI
0041D32D E84AFFFFFF      call TTest.WriteInt
0041D332 33C0             xor eax,eax
0041D334 5A              pop edx
0041D335 59               pop ecx
0041D336 59               pop ecx
0041D337 648910           mov fs:[eax],edx
0041D33A 684FD34100       push $0041d34f
Project765.dpr.46: lTest.Free;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
39.180 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: Seltsames Phänomen: Unterschied zwischen Integer und Int64

  Alt 9. Jan 2021, 14:20
Die Frage ist nur: Warum funktioniert es unter 32Bit nicht?
Es ist ein komplett anderer Compiler.
Im Win32 wird Int64 auch noch "emuliert", denn die CPU hat ja nur 32 Bit, also das +1 berechnet nicht die CPU mit "einem" Assemblerbefehl, sondern es erledigt Delphi, über zwei Int32. Teilweise über monströse Funktionen in der System.pas.

Delphi-Quellcode:
// Win32
Unit1.pas.29: X := X + 1;
0060E3A9 8B45F0 mov eax,[ebp-$10]
0060E3AC 8B55F4 mov edx,[ebp-$0c]
0060E3AF 83C001 add eax,$01
0060E3B2 83D200 adc edx,$00
0060E3B5 8945F0 mov [ebp-$10],eax
0060E3B8 8955F4 mov [ebp-$0c],edx

// Win64
Unit1.pas.29: X := X + 1;
000000000070ADA8 4883450801 add qword ptr [rbp+$08],$01
Delphi-Quellcode:
{ 64-bit Integer helper routines }
{$IF defined(CPU386) and defined(ASSEMBLER)}
procedure __llmul;
procedure __lldiv;
procedure __lludiv;
procedure __llmod;
procedure __llmulo;
procedure __llumulo;
procedure __lldivo;
procedure __llmodo;
procedure __llumod;
procedure __llshl;
procedure __llushr;
{$ENDIF}
In Win32 sieht der Aufruf also quasi so aus
lTest.SetTo2(lCount).SetI(__lladd(lCount, 1)).WriteInt; // __lladd ist aber eine Inline-Funktion vom Compiler
und hier wird das __lladd wohl zu früh ausgeführt, vor SetTo2.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014

Geändert von himitsu ( 9. Jan 2021 um 14:35 Uhr)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:41 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf