Verschiedene Variablen auf gleiche Speicherstelle

Rund um die LCL und andere Komponenten
Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Verschiedene Variablen auf gleiche Speicherstelle

Beitrag von Timm Thaler »

Ich habe gerade eine Denkblockade: Wie lege ich verschiedene Variablen auf die gleiche Speicherstelle?

Ich habe 2 Variablen
hh, mm : uint8;
und 1 Variable
time : uint16;

In hh und mm werden Stunden und Minuten als gepackte BCD-Zahl gespeichert, das obere Nibble enthält also die Zehner, das untere Nibble die Einer.

Jetzt möchte ich die Variable time so ablegen, dass deren oberes Byte hh, das untere Byte mm enthält. Ich weiss dass das geht, aber ich komme gerade nicht drauf wie. Ich brauche das für den einfachen Vergleich von Uhrzeiten.

Ich könnte hh,mm auch als Record anlegen, würde das was bringen?

Compiliert werden soll für Embedded AVR, aber das sollte ja egal sein.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Verschiedene Variablen auf gleiche Speicherstelle

Beitrag von mse »

Timm Thaler hat geschrieben:Ich könnte hh,mm auch als Record anlegen, würde das was bringen?

Ja. "Offiziell" darfst du dich nicht darauf verlassen, dass zusammenhängend definierte Variablen auch zusammenhängend im Speicher abgelegt werden.

Code: Alles auswählen

 
type
 timeelementsty = packed record //little endian
  mm: uint8;
  hh: uint8;
 end;
 
 timety = packed record
  case integer of
   0: (elements: timeelementsty);
   1: (time: uint16);
  end;
 

Ungeprüft!

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1432
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Verschiedene Variablen auf gleiche Speicherstelle

Beitrag von fliegermichl »

Hallo,

Das geht auch mit "absolute"

Code: Alles auswählen

 
var
 mm : uint8;
 hh : uint8;
 time : uint16 absolute mm;
 


das sorgt dafür, daß die Variable time an der Speicherstelle anfängt wie die mit absolute angegebene.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1432
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Verschiedene Variablen auf gleiche Speicherstelle

Beitrag von fliegermichl »

bei der Lösung von mse ist es übrigens nicht nötig zwei records zu definieren.

Code: Alles auswählen

 
type
 TTimeRec = packed record
  case integer of
   0 : (mm, hh : uint8);
   1 : (time : uint16);
 end;
 


geht auch.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Verschiedene Variablen auf gleiche Speicherstelle

Beitrag von mse »

fliegermichl hat geschrieben:Das geht auch mit "absolute"

Das ist dann aber nicht "offiziell", siehe oben.

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Verschiedene Variablen auf gleiche Speicherstelle

Beitrag von Timm Thaler »

Hm, das "packed record" hab ich gesehen, war mir aber nicht sicher, ob das "meine" Lösung ist.

Ist das immer "little endian", oder nur auf dem AVR?

Ich hab auch was mit "references" gelesen, finde aber keine Infos dazu. Such mal nach "fpc reference"... hunderte Einträge, aber nicht zielführend. ;-)

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1432
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Verschiedene Variablen auf gleiche Speicherstelle

Beitrag von fliegermichl »

Wenn ich mir die Freepascal Dokumentation anschaue, dann steht bei
6. The sixth form declares a variable (curterm6), and tells the compiler that it is stored in the same location as another variable (curterm1).

Ich kann nirgends "nicht offiziell" finden?!?

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Verschiedene Variablen auf gleiche Speicherstelle

Beitrag von mse »

Timm Thaler hat geschrieben:Ist das immer "little endian", oder nur auf dem AVR?

Die gezeigte Struktur ist für little endian. Universell:

Code: Alles auswählen

 
 timeelementsty = packed record
 {$ifdef endian_little}
  mm: uint8;
  hh: uint8;
 {$else}
  hh: uint8;
  mm: uint8;
 {$endif}
 end;
 

Ich hab auch was mit "references" gelesen, finde aber keine Infos dazu.

"references" als FPC Token? Das kenne ich nicht.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Verschiedene Variablen auf gleiche Speicherstelle

Beitrag von mse »

fliegermichl hat geschrieben:Ich kann nirgends "nicht offiziell" finden?!?

Man darf nicht erwarten, dass in

Code: Alles auswählen

 
var
 mm : uint8;
 hh : uint8;
 

"hh" ein Byte nach "mm" im Speicher liegt. Der Compiler kann Variablen im Speicher anlegen wie es ihm passt.

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Verschiedene Variablen auf gleiche Speicherstelle

Beitrag von Timm Thaler »

mse hat geschrieben:"hh" ein Byte nach "mm" im Speicher liegt. Der Compiler kann Variablen im Speicher anlegen wie es ihm passt.


Und bei Records? Liegt bei

Code: Alles auswählen

timetype = packed record
  mm: uint8;
  hh: uint8;
 end;

hh immer direkt hinter mm, little endian vorausgesetzt?

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1432
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Verschiedene Variablen auf gleiche Speicherstelle

Beitrag von fliegermichl »

Timm Thaler hat geschrieben:
mse hat geschrieben:"hh" ein Byte nach "mm" im Speicher liegt. Der Compiler kann Variablen im Speicher anlegen wie es ihm passt.


Und bei Records? Liegt bei

Code: Alles auswählen

timetype = packed record
  mm: uint8;
  hh: uint8;
 end;

hh immer direkt hinter mm, little endian vorausgesetzt?


Meiner Meinung nach ja, sonst würden Deklarationen wie array of record oder file of record nicht funktionieren.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Verschiedene Variablen auf gleiche Speicherstelle

Beitrag von mse »

Timm Thaler hat geschrieben:Und bei Records? Liegt bei

Code: Alles auswählen

timetype = packed record
  mm: uint8;
  hh: uint8;
 end;

hh immer direkt hinter mm, little endian vorausgesetzt?

Immer, sogar unbhängig von little- oder big-endian.

Mathias
Beiträge: 6165
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Verschiedene Variablen auf gleiche Speicherstelle

Beitrag von Mathias »

Immer, sogar unbhängig von little- oder big-endian.

Bei diesem Code, könnte ich mir vorstellen, das es eine Rolle spielt.

Code: Alles auswählen

type
 TTimeRec = packed record
  case integer of
   0 : (mm, hh : uint8);
   1 : (time : uint16);
 end;

Noch ein Hinweis, wen man Daten mit Java austauscht, dann muss man little- und big-endian beachten.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Verschiedene Variablen auf gleiche Speicherstelle

Beitrag von mse »

Mathias hat geschrieben:
Immer, sogar unbhängig von little- oder big-endian.

Bei diesem Code, könnte ich mir vorstellen, das es eine Rolle spielt.

Code: Alles auswählen

type
 TTimeRec = packed record
  case integer of
   0 : (mm, hh : uint8);
   1 : (time : uint16);
 end;


Ja, dieser TTimeRec ist ausschliesslich für little-endian systeme.

Timm Thaler
Beiträge: 1224
Registriert: So 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded
CPU-Target: Raspberry Pi 3

Re: Verschiedene Variablen auf gleiche Speicherstelle

Beitrag von Timm Thaler »

Bösartige Frage: Ist es möglich, den Record so zu modifizieren, dass ich drei Bytewerte habe, aber nur aus 2en ein Word mache?

hh, mm, ss : uint8 // so sieht meine Uhrzeit aus, die ich von der RTC bekomme
hhmm // das ist mein Zeitwert, auf den ich vergleiche

Ich würde also gern "time" so auf hh,mm,ss mappen, dass im Highbyte hh, im Lowbyte mm stehen und ss nicht beachtet wird.

Code: Alles auswählen

type
 TTimeRec = packed record
  case integer of
   0 : (ss, mm, hh : uint8);
   1 : (ss : uint8; time : uint16);
 end;
 

Wird sicher nicht gehen, weil ja der case so nicht funktioniert.

Code: Alles auswählen

type
 TTimeRec = packed record
  case integer of
   0 : (mm, hh, ss : uint8);
   1 : (time : uint16; ss : uint8);
 end;
 

Könnte vielleicht gehen, aber die Reihenfolge mm, hh, ss ist natürlich unschön.

Antworten