Hallo,
ich würde gerne unten stehende Strukturen sowohl über Ihren Namen
ansprechen, als auch über Indizes. Damit will ich mir die Möglichkeit
schaffen, die Daten in einer for-Schleife auf ein Display zuschreiben.
Für die bessere Lesbarkeit im Quelltext würde ich aber trotzdem gerne
über ihren Namen auf die Strukturen zugreifen, also beispielsweise
'L1.val'.
Direkt ein Array mit den Strukturen zu erzeugen, scheidet wohl aus, weil
die Datentypen unterschiedlich lang sein können. Was ich mir aber
vorstellen könnte, wäre ein weiteres Array, indem die Startadresse von
jeder Struktur liegt. In der for-schleife könnte ich dann mittels
pointer auf die jeweilige Struktur zugreifen. Ich überblicke gerade noch
nicht, ob das funktionieren könnte und ist das ein vernünftiger und
machbarer Weg, oder gibt es ein eleganteres herangehen?
[c]typedef struct{
uint8_t pos_x;
uint8_t pos_y;
uint8_t visible;
char unit;
}TEXT;
typedef struct{
TEXT Text;
uint16_t val;
}DATA;
typedef struct{
TEXT Text;
uint16_t val;
uint16_t val_tmp;
}EXTENDED;
DATA L1={first_column, bottom_row, true, 'A', 0},
L2={second_column, bottom_row, true, 'A', 0},
L3={third_column, bottom_row, true, 'A', 0},
Imin={first_column, second_row, true, 'A',0},
Imax={third_column, second_row, true, 'A',0};
EXTENDED Time={second_column, second_row, true, 'M', 0, 0};/c
Vielen Dank
Jochen
Hmm...
Bei unterschiedlich langen Strukturen kann man verkettete Listen
verwenden.
Ist aber mit Vorsicht zu genießen..
Dynamische Speicherverwaltung will man auf µC eigentlich nicht. Oder?
Guten Morgen Karl,
vielen Dank für deine schnelle Antwort. Über unions bin ich gestern auch
gestolpert. Habs aber noch nicht so gut verstanden, um es auch umsetzen
zu können.
Kannst du mir noch einen kurzen Denkanstoß, bezogen auf mein Beispiel,
geben?...das wäre nett.
Jochen
>weil die Datentypen unterschiedlich lang sein können
Sowas existiert in den Objektverzeichnissen von CANopen.
Dort können die Datentypen auch unterschiedlich sein. Um das generisch
intern zu handeln, wird (zB) die Startadresse der Struktur und die Länge
jedes Members mitgegeben.
>ich beim automatisierten Zugriff immer auf die gleiche Länge zugreife?
Dann musst Du Füllbytes einsetzen und alles auf gleiche maximale Länge
auffüllen. Das Problem bleibt aber noch, das Du nicht weisst, wielang
das Element wirklich ist.
Die verschiedenen Strukturen auf die gleiche Länge bringen ist nur die
halbe Miete. Du hast zwar dann alles schön in einem Array aber du willst
ja auch auf die verschiedenen Member der Strukturen zugreifen und da
muss du den Typ der Struktur mitführen damit du auf die richtige
Struktur casten kannst.
Also entweder mit union und mit zusätzlichem type member oder mit einer
zusätzlichen struktur
typedef struct {
uint8_t type; // DATA = 0, EXTENDED = 1, ...
void* data;
} UNIDATA;
Hallo,
ich komme nicht dahinter wie mir unions bei der Indizierung helfen
könnten. Ich hätte wohl auch nicht zwei Schritte auf einmal tun
sollen.:-) Vielleicht ist es mit einer einzelnen Struktur einfacher zu
begreifen.
1
typedefstruct{
2
uint8_tpos_x;
3
uint8_tpos_y;
4
uint8_tvisible;
5
charunit;
6
}DATA;
jetzt kann ich:
1
DATAL1,L2,L3,Imax,Imin;
2
L1.pos_x=0x00;
oder eben:
1
DATAa[5];
2
a[0].pos_x=0x00;
Soweit verstehe ich, aber wie schaffe ich es jetzt mit Hilfe von unions
den Zugriff auf beide Arten zu realisieren?
Jochen schrieb:> Soweit verstehe ich, aber wie schaffe ich es jetzt mit Hilfe von unions> den Zugriff auf beide Arten zu realisieren?
mit einer union legst du über denselben Speicherbereich eine andere
Datenstruktur drüber.
Aber Achtung: offiziell ist das nur im Ausnahmefall erlaubt, dass du zb
ein unsigned char Array über den Speicher legst.
Trotzdem ist diese Technik seit Jahrzehnten gang und gäbe.
1
typedefstruct{
2
uint8_tpos_x;
3
uint8_tpos_y;
4
uint8_tvisible;
5
charunit;
6
}DATA;
7
8
unionData_t
9
{
10
DATAd;
11
uint8_tbytes[4];
12
};
13
14
Data_tmeineDaten;
meineDaten.d und meineDaten.bytes liegen im Speicher übereinander.
Eine etwas andere Mögllichkeit wäre zb das Arbeiten mit dem Präprozessor
:-)
Immer daran denken. Wenn dir im Quelltext irgendetwas textuell nicht
gefällt, dann gibt es oft Mögllichkeiten wie du mit dem Präprozessor
eine alternative Schreibweise erzielen kannst.
Du hast zb ein Array
1
uint8_tdaten[5];
um auf das Element mit dem Index 1 zuzugreifen, müsstest du schreiben
1
daten[1]=8;
jetzt möchtest du aber nicht [1] schreiben, weil dir das zuwenig
aussagekräftig ist. Statt dessen möchtest du zb lieber
1
daten[Y_POS]=8;
schreiben können.
(Gewöhn dir am besten gleich an, dass du derartige Text-Magie immer in
Grossbuchstaben und ausschliesslich in Grossbuchstaben schreibst. Und
auch umgekehrt: ausschliesslich Grossbuchstaben bedeutet, dass es sich
um ein Präprozessormakro handelt)
Um das gewünschte zu erreichen, würde es genügen, wenn vor dem
Compilerlauf irgendjemand den Text Y_POS gegen den Text 1 austauscht.
Na genau das kann aber der Präprozessor. SChreibst du dir ein Makro
1
#define Y_POS 1
dann passiert genau das: Der Präprozessor sieht die Zeile
1
daten[Y_POS]=8;
und weil er das Makro
1
#define Y_POS 1
vorher schon gesehen hat, tauscht er den Text Y_POS gegen den Text 8
aus. Als Ergebnis entsteht
1
daten[1]=8;
das erstens genau so beabsichtigt war und das zweitens dann zum
eigentlichen Compiler geht, der es übersetzt.
Hallo Karlheinz,
das verstehe ich dann, aber dann muss ich doch trotzdem bei einem
gezielten Zugriff den index kennen. Ich möchte ja doch mehrere Variablen
vom typ DATEN erzeugen
Karl H. schrieb:> und weil er das Makro> #define Y_POS 1> vorher schon gesehen hat, tauscht er den Text Y_POS gegen den Text 8> aus. Als Ergebnis entsteht> daten[1] = 8;
Wäre das dann nicht
daten[8] = 8;
?
Jochen schrieb:> Hallo Karlheinz,>> das verstehe ich dann, aber dann muss ich doch trotzdem bei einem> gezielten Zugriff den index kennen.
Logisch. So funktioniert nun mal ein Array.
> Ich möchte ja doch mehrere Variablen> vom typ DATEN erzeugen
Du erzeugst dann eben nicht vom Typ Daten, sondern vom Typ Data_t
Entweder du willst etwas erreichen, dann musst du auch den Aufwand dafür
schlucken.
Oder du lässt es.
C ist nun mal eine statisch typisierte Sprache. Zur Laufzeit ist
keinerlei Information mehr vorhanden, was das da im Speicher darstellen
soll.
Das hat Vorteile, zum Beispiel den, dass du die Kontrolle darüber hast,
was im Speicher angelegt wird und was nicht.
Das hat aber auch Nachteile. So etwas wie Reflection ist in C aus dem
Stand heraus nicht möglich, sondern man muss es sich selbst
programmieren, wenn man das möchte.
Umsonst ist der Tod. Und der kostet das Leben.
Hannes schrieb:> Karl H. schrieb:>> und weil er das Makro>> #define Y_POS 1>> vorher schon gesehen hat, tauscht er den Text Y_POS gegen den Text 8>> aus. Als Ergebnis entsteht>> daten[1] = 8;>> Wäre das dann nicht> daten[8] = 8;> ?
Der Tippfehler sitzt hier
> tauscht er den Text Y_POS gegen den Text 8
Der wird natürlich nicht gegen 8 sondern gegen 1 getauscht. Das Makro
war ja schliesslich