Variablen überlagern
Variablen überlagern
Hallo Forum,
ich bin die ganze Zeit am grübeln, wie folgendes in Lazarus umgesetzt werden kann:
Ich habe eine Variable Test :Array[2] of char;
Und möchte die Variable Test1:Byte auf die Adresse von Test legen.
Var
Test :Array[2];
Test1[@Test]:Byte;
So in der Art.
Kann ich das irgendwie bewerkstelligen?
Danke an Alle!
ich bin die ganze Zeit am grübeln, wie folgendes in Lazarus umgesetzt werden kann:
Ich habe eine Variable Test :Array[2] of char;
Und möchte die Variable Test1:Byte auf die Adresse von Test legen.
Var
Test :Array[2];
Test1[@Test]:Byte;
So in der Art.
Kann ich das irgendwie bewerkstelligen?
Danke an Alle!
-
- Beiträge: 153
- Registriert: Sa 30. Jan 2010, 18:17
- OS, Lazarus, FPC: Windows 10 64Bit/ lazarus 3.0 mit FPC 3.2.2 (32Bit + 64bit)
- CPU-Target: 64Bit
- Wohnort: Berlin
Re: Variablen überlagern
Hallo,
dafür brauchts du eine Pointer-Variable, in der du dann die Adresse des Array-Feldes speichern kannst. Wenn du dann auf den Wert dieses Feldes über die Pointervariable zugreifen möchtest, muss du dem Compiler mitteilen, dass du den Wert an der Adress meinst (derefernzieren). Das machst du, indem du das ^-Zeichen hinter der Variablennamen anhängst.
dafür brauchts du eine Pointer-Variable, in der du dann die Adresse des Array-Feldes speichern kannst. Wenn du dann auf den Wert dieses Feldes über die Pointervariable zugreifen möchtest, muss du dem Compiler mitteilen, dass du den Wert an der Adress meinst (derefernzieren). Das machst du, indem du das ^-Zeichen hinter der Variablennamen anhängst.
Code: Alles auswählen
var Test :Array[0..2] of char;
pTest1 : ^Char;
...
pTest1 := @Test[0];
pTest1^ := 'H';
WriteLn(pTest1^);
Re: Variablen überlagern
Hallo Thandor,
vielen Dank!
Ich dachte, man kann das schon während der Deklaration dem Compiler mitteilen.
Viele Grüße
vielen Dank!
Ich dachte, man kann das schon während der Deklaration dem Compiler mitteilen.
Viele Grüße
- af0815
- Lazarusforum e. V.
- Beiträge: 6770
- Registriert: So 7. Jan 2007, 10:20
- OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
- CPU-Target: 32Bit (64Bit)
- Wohnort: Burgenland
- Kontaktdaten:
Re: Variablen überlagern
Du meinst https://wiki.freepascal.org/Absolute
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).
-
- Beiträge: 954
- Registriert: Mi 3. Jun 2020, 07:18
- OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
- CPU-Target: Aarch64 bis Z80 ;)
- Wohnort: München
Re: Variablen überlagern
Wie af0815 angedeutet hat, das Zauberwort ist absolute:
Code: Alles auswählen
program tabs;
var
test: array[0..1] of Byte;
test1: Byte absolute test[0];
begin
test[0] := 42;
test[1] := 21;
Writeln(test1);
end.
FPC Compiler Entwickler
-
- Beiträge: 153
- Registriert: Sa 30. Jan 2010, 18:17
- OS, Lazarus, FPC: Windows 10 64Bit/ lazarus 3.0 mit FPC 3.2.2 (32Bit + 64bit)
- CPU-Target: 64Bit
- Wohnort: Berlin
Re: Variablen überlagern
Das Schlüsselwort absolute kannte ich bisher noch nicht. Gut ich habe diese Mechanik noch nie gebraucht, also habe ich noch nie nach diesr Möglichkeit gesucht.
Aber wo ist sowas eigentlich sinvoll? Macht das am Ende den Code nicht erhr unleserlich? Da wird doch dann der eigentliche Typ (hier ein Array) verschleiert?
Aber wo ist sowas eigentlich sinvoll? Macht das am Ende den Code nicht erhr unleserlich? Da wird doch dann der eigentliche Typ (hier ein Array) verschleiert?
-
- Beiträge: 2118
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Variablen überlagern
Nein ist es nicht, vor allem weil es compilerchecks ausschaltet:Thandor hat geschrieben: Fr 19. Aug 2022, 11:10 Aber wo ist sowas eigentlich sinvoll? Macht das am Ende den Code nicht erhr unleserlich? Da wird doch dann der eigentliche Typ (hier ein Array) verschleiert?
Code: Alles auswählen
var
b: Byte;
i: Integer absolute b;
begin
i := $0FFFFFFF;
end.
Code: Alles auswählen
{$T+}
var
b: Byte;
i: PInteger = @b; // Incompatible types: got "^Byte" expected "PInteger"
begin
i^ := $0FFFFFFF;
end.
Das heist nicht das man keinen Fehleranfälligen code mehr schreiben können sollte, also z.B. wenn man unbedingt auf einen byte typen als integer zugreifen will dann gibt es da möglichkeiten. Aber wenn man was spezielles macht, sollte das auch speziell gekennzeichnet sein. Wenn man absolute benutzt sieht jeder zugrif auf die variable so aus als würde man eine normale variable verändern, aber eigentlich ist es ein pointer. Bei einem "echten" pointer, hat man die pointer syntax die ganz klar kennzeichnet das es ein pointer ist:
Code: Alles auswählen
var
b: Byte;
p: PByte = @b;
a: Byte absolute b;
begin
p^ := 42; // ^ zeigt ganz klar das hier ein wert geschrieben wird der woanders liegt
a := 42; // wenn man nicht weis das a absolute ist lässt es das so aussehen als wäre a eine eigene variable
Code: Alles auswählen
arr: Array[0..3] of Byte;
begin
PInteger(@arr[0])^ := 42;
Mein Favorit ist aber eigentlich die verwendung von Varianten Records:
Code: Alles auswählen
var
data: record
case Boolean of
True: (asArray[0..3] of Byte);
False: (asInteger: Integer);
end;
begin
data.asInteger := 42;
WriteLn(data.asArray[0]);
1. es ist sicher, der variante record ist immer so groß wie das größte case, also selbst wenn asArray 0..2 wäre, also kleiner als ein integer, würde der variante record immer mindestens die größe des Integers belegen, und man schreibt niemals über in fremden speicher, sowohl mit pointern als auch mit absolute kann man über die speicher boundaries schreiben, mit varianten records nicht.
2. es ist explizit, data.asInteger und data.asArray zeigen durch das "data" das sie zum selben speicherobjekt gehören, und durch explizite namensgebung "asXXX" ist auch klar das das eine reinterpretation der daten ist.
3. die deklarationen sind am selben Ort. wenn du jetzt von 32 bit auf 63 bit upgradest und daher aus i: Integer ein asInteger: Int64 machst, bist du direkt an dem ort an dem auch asArray deklariert ist und siehst direkt: Hey ich muss das auch noch ändern. Bei absolute oder pointern können hunderte zeilen code zwischen den beiden punkten liegen, sodass du, weil du vielleicht neu an dem projekt bist, nicht einmal weist das diese aboslute referenz existiert
Daher faustregel: Benutz absolute niemals, pointer für referenzen auf den selben datentypen und für zugriff mittels verschiedenen datentypen veriante records. Es gibt Fälle da sind Pointer einfacher (stichwort Pointerarithmethik), aber variante records sind eigentlich fast immer zu bevorzugen
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1639
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
Re: Variablen überlagern
Ich verwende absolute ziemlich oft.
Normalerweise wenn ich auf einzelne Bytes einer größeren Variable zugreifen will.
Normalerweise wenn ich auf einzelne Bytes einer größeren Variable zugreifen will.
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1639
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
Re: Variablen überlagern
Oder wenn ich auf spezielle Properties von Klassen zugreifen will, die von der gleichen Basisklasse abgeleitet sind.
Code: Alles auswählen
type
TBase = class;
TPunkt = class ( TBase )
end;
TFlaeche = class ( TBase )
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var b : TBase;
p : TPunkt absolute b;
f : TFlaeche absolute b;
begin
b := FangeObjekt(x, y);
if (b is TPunkt) then
p.xxx
else if (b is TFlaeche) then
f.xxx;
end;
Re: Variablen überlagern
Kannst du mir erklären, wozu das gut ist?fliegermichl hat geschrieben: Fr 19. Aug 2022, 13:14 Oder wenn ich auf spezielle Properties von Klassen zugreifen will, die von der gleichen Basisklasse abgeleitet sind.
Warum nicht einfach:
Code: Alles auswählen
if b is TPunkt then (b as TPunkt).xxx;
-
- Beiträge: 758
- Registriert: Di 23. Aug 2016, 14:25
- OS, Lazarus, FPC: Windows 11
- CPU-Target: 64Bit
- Wohnort: Berlin
Re: Variablen überlagern
Absolute ist eigentlich unumgänglich für Embedded Anwendungen.Thandor hat geschrieben: Fr 19. Aug 2022, 11:10 Das Schlüsselwort absolute kannte ich bisher noch nicht. Gut ich habe diese Mechanik noch nie gebraucht, also habe ich noch nie nach diesr Möglichkeit gesucht.
Aber wo ist sowas eigentlich sinvoll? Macht das am Ende den Code nicht erhr unleserlich? Da wird doch dann der eigentliche Typ (hier ein Array) verschleiert?
So werden die Register des Controllers definiert, die ja immer an einer festen Adresse liegen.
Beispielsweise so:
Code: Alles auswählen
const SYSTICK_BASE_ADDRESS = $E000E010; // Basisadresse beim STM32Fxxx
var STK_CTRL : DWORD absolute SYSTICK_BASE_ADDRESS + 0; // Steuerung interupt Clock select usw.
var STK_LOAD : DWORD absolute SYSTICK_BASE_ADDRESS + 4; // Zaehlerwert welcher beim Erreichen von 0 wieder geladen werden soll
var STK_VAL : DWORD absolute SYSTICK_BASE_ADDRESS + 8; // aktuelle Zählerstand des 24 Bit Zählers
begin
STK_CTRL := 7; // counter enable, enable interrupt
.....
Grüße von Siro
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...
Bevor ich "C" ertragen muß, nehm ich lieber Lazarus...
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1639
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
Re: Variablen überlagern
Aus Gründen der Faulheit. Meistens muss man mehr als nur eine Operation auf der Variablen ausfuehren.theo hat geschrieben: Fr 19. Aug 2022, 13:27Kannst du mir erklären, wozu das gut ist?fliegermichl hat geschrieben: Fr 19. Aug 2022, 13:14 Oder wenn ich auf spezielle Properties von Klassen zugreifen will, die von der gleichen Basisklasse abgeleitet sind.
Warum nicht einfach:Code: Alles auswählen
if b is TPunkt then (b as TPunkt).xxx;
-
- Beiträge: 153
- Registriert: Sa 30. Jan 2010, 18:17
- OS, Lazarus, FPC: Windows 10 64Bit/ lazarus 3.0 mit FPC 3.2.2 (32Bit + 64bit)
- CPU-Target: 64Bit
- Wohnort: Berlin
Re: Variablen überlagern
Danke für eure Antworten.
Ja, dass es ein paar Fälle gibt, die das "absolute" benötigen habe ich mir schon gedacht. Aber der Anwendungsfall, wie hier am Threadanfang eingeführt sollte mann meiden.
Ja, dass es ein paar Fälle gibt, die das "absolute" benötigen habe ich mir schon gedacht. Aber der Anwendungsfall, wie hier am Threadanfang eingeführt sollte mann meiden.
-
- Beiträge: 2118
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Variablen überlagern
Auch hier ist absolute eine schlechte idee, da es compilerchecks ausschaltet:fliegermichl hat geschrieben: Fr 19. Aug 2022, 13:14 Oder wenn ich auf spezielle Properties von Klassen zugreifen will, die von der gleichen Basisklasse abgeleitet sind.
Code: Alles auswählen
TBase = class
public
Foo: Integer;
end;
TChild1 = class(TBase);
TOther = class(TObject);
var
o: TOther;
b: TBase;
c: TChild1 absolute b;
wrong: TChild1 absolute o; // Fehler aber keine fehlermeldung
Code: Alles auswählen
var
o: TOther;
begin
TChild1(o).Foo := 42; // Warning: Class types "TOther" and "TChild1" are not related
(o as TChild1).Foo := 42; // Error: Class or Object types "TOther" and "TChild1" are not related
Code: Alles auswählen
TBase = class
public
Foo: Integer;
end;
TChild1 = class(TBase);
TChild2 = class(TBase);
var
b: TBase;
begin
b := TChild2.Create;
(b as TChild1).Foo := 42; // Runtime Error
end.
-
- Beiträge: 954
- Registriert: Mi 3. Jun 2020, 07:18
- OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
- CPU-Target: Aarch64 bis Z80 ;)
- Wohnort: München
Re: Variablen überlagern
Der as-Operator ist vergleichsweise teuer (genauso wie der is-Operator) und den Hauptteil davon hast du ja schon mit is gemacht, warum also nochmal? Also entweder 'nen harten Cast oder absolute.theo hat geschrieben: Fr 19. Aug 2022, 13:27Kannst du mir erklären, wozu das gut ist?fliegermichl hat geschrieben: Fr 19. Aug 2022, 13:14 Oder wenn ich auf spezielle Properties von Klassen zugreifen will, die von der gleichen Basisklasse abgeleitet sind.
Warum nicht einfach:Code: Alles auswählen
if b is TPunkt then (b as TPunkt).xxx;
FPC Compiler Entwickler