Hallo Leute,
dies ist eine Frage an die Ada-Profis (vielleicht auch SPARK/VHDL), wie
ich es gerne einmal, wenn ich groß bin, werden möchte. Vielleicht gibt
es ja hier auch einen der scheinbar sehr exotischen/seltenen
Ada-Programmiere.
Eigentlich komme ich aus der C-Ecke und habe mit Ada da noch so manche
Probleme.
Konkret habe ich eine Frage, die ich zwar in C lösen kann, aber kein
Ada-Gegenspieler finde. - oder, das will ich nicht ausschießen, momentan
noch zu unerfahren bin.
Ich will einen Datentyp (eine "Record" 32Bit breit) erzeugen und
beispielsweise als 4x8Bit Datentyp benutzen. Das geht ja (zumindest die
erste meiner Anforderungen) seit mind. Ada95 über die "Record
Representation Clauses". - Analog dazu in C wäre ja ein Union.
1
typeBYTEismod2**8;
2
typeDatais
3
record
4
BYTE_1:BYTE;
5
BYTE_2:BYTE;
6
BYTE_3:BYTE;
7
BYTE_4:BYTE;
8
endrecord;
9
10
forDatause
11
record
12
BYTE_1at0range0..7;
13
BYTE_2at0range8..15;
14
BYTE_3at0range16..23;
15
BYTE_4at0range24..31;
16
endrecord;
Wenn ich die Größe des Records abfrage, bekomme ich als Antwort 32 (Bit)
zurück geliefert. Das geht also schon einmal :-)
Jetzt würde ich aber diesen Record einen 32Bit Wert zuweisen.
Auch das folgende geht leider nicht. Die Idee eine 32Bit Variable in den
Record zu legen, der die selbe Adresse hat wie die 4 Bytes zuvor
sozusagen eine Überladung/Überlagerung:
1
typeBYTEismod2**8;
2
typeDWORDismod2**32
3
typeDatais
4
record
5
BYTE_1:BYTE;
6
BYTE_2:BYTE;
7
BYTE_3:BYTE;
8
BYTE_4:BYTE;
9
DWORD_1:DWORD;
10
endrecord;
11
12
forDatause
13
record
14
BYTE_1at0range0..7;
15
BYTE_2at0range8..15;
16
BYTE_3at0range16..23;
17
BYTE_4at0range24..31;
18
DWORD_1at0range0..31;-- Idee: Benutzt den selben Bereich wie die anderen Bytes
19
endrecord;
Da spuckt mir der Compiler "component "DWORD_1" overlaps "BYTE_1" at
line xxx" aus. Ja, das war ja auch die Idee dahinter, aber scheinbar ist
es unzulässig - "C" hat mich halt versaut :-(
Generell wollte ich es so machen um nicht zu viel des kostbaren
Speichers zu benutzen; in einem Zug große Mengen an Werten kompakt zu
schreiben und einzelne Bytes eines 32Bit Werts einfach zu manipulieren.
Kann mir jemand sagen, ob es so in der Art überhaupt geht? - Und wenn
ja, wie?
PS: Ich Formatiere den Code als VHDL damit die Forumsoftware sie etwas
aufhübscht ;)
Erste Frage: Warum tust du so eine Schweinerei?
Erste Antwort:
du könntest eine unchecked_conversion DWORD -> Data benutzen, das geht
auf jeden Fall.
ABER: wie der Name schon sagt ist das ganze dann ohne Typprüfung. Bei
deinem Record ist das noch kein Problem weil es keinen DWORD-Datentyp
gibt der einen illegalen "Data"-Record darstellt. Aber wenn du jetzt
z.B. das BYTE_2 auf ein myint änderst der range 0 .. 200 hat, dann gibt
es plötzlich illegale Werte. Wenn du nun über eine unchecked_conversion
einen illegalen Wert in deinen Record lädst, dann kracht es irgendwann
beim Zugriff auf den Record. (NICHT!! beim Zuweisen, das ist ja
unchecked).
Vielen Dank schon einmal.
Wie würde man den so etwas den Ada-Regeln entsprechend implementieren?
Wie gesagt, ich lerne noch, kenne noch nicht alle Kniffe und bin von C
versaut.
Was genau möchtest du denn erreichen?
Ada-Neuling schrieb:> Generell wollte ich es so machen um nicht zu viel des kostbaren> Speichers zu benutzen; in einem Zug große Mengen an Werten kompakt zu> schreiben und einzelne Bytes eines 32Bit Werts einfach zu manipulieren.
Nur um es kompakt zu schreiben?
Dann setz lieber die vier Bytes nacheinander. Der Compiler macht sehr
wahrscheinlich am Ende das gleiche daraus.
Wenn du mehr ernsthaften Ada-Code schreiben willst, dann wird das eh auf
Dauer nichts weil deine Datentypen nicht spezifisch genug sind.
Wenn ich auf unsere Ada-Codebase schaue (Millionen LOC), dann sind die
Ada-Standarddatentypen sehr selten.
Die meisten Variablen (und Record member) sind von einem Typ, der genau
dem Inhalt entspricht.
Also wenn ich einen Record mit Luftdruck, Temperatur und Luftfeuchte
habe, dann sind da nicht 3 floats drin, sondern ein T_air_pressure, ein
T_temperature und ein T_humidity. Somit kann man die nicht ausversehen
mit anderen Dingen vermischen (Temperatur + Druck = Banane).
Torben H. schrieb:> Wenn ich auf unsere Ada-Codebase schaue (Millionen LOC), dann sind die> Ada-Standarddatentypen sehr selten.
Cool, dann gibt es ja doch noch ein paar Entwickler, die diese an sich
coole alte Sprache noch nutzen :)
Das freut mich ungemein und steigert auch meine Entschlossenheit damit
weiter zu machen!
Torben H. schrieb:> Die meisten Variablen (und Record member) sind von einem Typ, der genau> dem Inhalt entspricht.> Also wenn ich einen Record mit Luftdruck, Temperatur und Luftfeuchte> habe, dann sind da nicht 3 floats drin, sondern ein T_air_pressure, ein> T_temperature und ein T_humidity. Somit kann man die nicht ausversehen> mit anderen Dingen vermischen (Temperatur + Druck = Banane).
Ja okay, leuchtet in der strengen Typisierung, die Ada einem vorgibt
ein. Macht den Code auch ohne Ausführung deutlich lesbarer.
P.S. schrieb:> Da es sich um einen Record handelt, nimmt man ein Record-Aggregat.
Das macht den Code auf jeden fall lesbarer als mein Ansatz. Ich glaube,
dieses "viel mit wenig beschreibung" machen zu wollen muss ich mir
abgewöhnen! - Ich muss die C-Denke im meinem Kopf noch etwas mehr
abblocken ;)
Apropro lesbar: Ich musste mal einen LEX/YACC Code von Hand optimieren.
Das war zwar C, was ich eigentlich beherrsche, aber sowas von kryptisch.
Ich habe tage lang den Code angestarrt, bevor ich darin anfangen konnte
zu arbeiten.
Ada Code ist für mich von Anfang an sehr gut lesbar gewesen, selbst als
ich die einfachsten Sprachelemente noch nicht kannte, wusste ich
meistens, was der Code bewirken soll. Dafür, das sie aus den ende der
'70er stammt, bei dem man mit jedem Bit geizig war, finde ich das eine
wirklich gelungene Sache!
Ada-Neuling schrieb:> Ada Code ist für mich von Anfang an sehr gut lesbar gewesen, selbst als> ich die einfachsten Sprachelemente noch nicht kannte, wusste ich> meistens, was der Code bewirken soll. Dafür, das sie aus den ende der> '70er stammt, bei dem man mit jedem Bit geizig war, finde ich das eine> wirklich gelungene Sache!
Ja, wirklich beeindruckend.. krass z.B. kenn ich es, da für Steuerungen
in Leitsystemen im Bahnverkehr das immer noch eingesetzt wird; deutscher
Konzern mit großem "S" am Anfang..
Hat zwar nur bedingt mit meinem ursprünglichem Post zu tun, aber ich
habe die letzten Tage wirklich viel über Ada gelernt! Genial, welche
Möglichkeiten man mit dieser Sprache hat. Es geht so weit, das man bei
selbst angelegten Variablen, sogar festlegen kann ob diese per Big oder
Little Indian angelegt werden soll. Das nenne ich mal Portabilität. Das
geht, soweit ich weiß unter C/C++ und Co nicht und ist immer vom
Compiler und/oder der Plattform abhängig abhängig.
Hier mal ein umfangreiches Beispiel
Word:Constant:=2;--numbers of storage units in a Word
10
Bits_In_Word:Constant:=16;--bits in word
11
typeCsr_Tisrecord
12
Error:Error_T;
13
Busy:Boolean;
14
Unit:Unit_T;
15
Done:Boolean;
16
Ienable:Boolean;
17
Dfun:Function_T;
18
Denable:Boolean;
19
endrecord;
20
forCsr_Tuse
21
record
22
Denableat0*Wordrange0..0;--at word 0 bit 0;
23
Dfunat0*Wordrange1..2;
24
-- bits 3-5 unused
25
Ienableat0*Wordrange6..6;
26
Doneat0*Wordrange7..7;
27
Unitat0*Wordrange8..10;
28
Busyat0*Wordrange11..11;
29
Errorat0*Wordrange12..15;
30
endrecord;
31
forCsr_T'SizeuseBits_in_Word;--the size of object of Csr type
32
forCsr_T'AlignmentuseWord;--object should be word aligned
33
forCsr_T'Bit_OrderuseSystem.Low_Order_First;--first bit is least significant bit of byte
Man kann Aufzählungstypen sogar einen Wert zuweisen, die das Abbild im
Speicher erzeugen soll oder dem Record sagen; wie groß es ist und wie
seine Ausrichtung oder seine Bitreinfolge ist - Und das
Plattformunabhängig.
Klar, das ist wirklich viel zum schreiben, aber ich glaube, wenn man
soetwas ich C/C++ macht (wenn es denn überhaupt geht), ist der
Schreibaufwand ähnlich groß. Aber wenn der Ada-Compiler das gefressen
hat, geht bei C/C++ das tagelange debuggen vermutlich erst los.
Mag vielleicht auch daran liegen, das der Ada-Programmierer sich
deutlich mehr um seinen Code Gedanken machen muss, als alle anderen.
Das war das Wort zum Sonntag ;)
Happy Coding euch allen :P
PS:
Nicht falsch verstehen, ich komme aus der Embedded C-Welt! Ich kenne,
liebe und verfluche es. Ich wollte einfach mal wieder was neues lernen,
nachdem ich zwei Wochen lang einen Bug in einem nicht von mir stammenden
C-Code gesucht habe und relativ frustriert war, wie weitreichend der
Code neu gestaltet werden musste, um ihn auszumerzen ohne die restliche
Funktion des Programms aufrecht zu halten. Noch dazu, da dieser Code auf
2 (x86 und ARM) von drei (x86, ARM, PPC) Plattformen lief, ohne Probleme
zu bereiten - was nicht heißen soll, das der Fehler auch nicht auf den
anscheinend Fehlerfreien Plattformen auftreten könnte :-/