Janvi schrieb:
> 1) Der struct SondenTel wird innerhalb der Union definiert. Das ist
> schlecht, wenn weitere Variablen mit dem gleichen Telegramminhalt an
> andere Stelle reserviert werden sollen.
Kein Mensch zwingt dich dazu, dass du die struct innerhalb der Union
definieren musst.
> 2) Die Reservierung des Puffers "DatTxBuf" erfolgt zusammen mit der
> Definition des Unions. Das ist schlecht, wenn weitere Puffer z. Bsp. für
> andere Uarts reserviert werden sollen.
Kein Mensch zwingt dich dazu, dass so zu machen. Deklariere die union
efinach mal und dann legst du beliebig viele Variablen davon an.
> Jetzt habe ich angenommen, daß der Union Name "TxArrayWortconverter" ein
> neuer Typname ist, unter welchem Variablen reserviert werden könnnen.
> D.h. in der Union Definition lasse ich am Ende "DatTxBuf" weg - der
> Strichpunkt bleibt. Mit "volatile TxAarrayConverter DatTxBuf2" kommt
> eine für mich unverständliche Meldung: error: expected '=', ',', ';',
> 'asm' or '__attribute__' before 'DatTxBuf2'
In C sind weder bei Strukturen noch bei Unions die Namen der struct bzw
der union automatisch neue Typnamen. Du musst immer struct bzw union
dazuschreiben
1 | struct Date
|
2 | {
|
3 | int day;
|
4 | int month;
|
5 | int year;
|
6 | };
|
7 |
|
8 |
|
9 | struct Date birthDay;
|
10 | struct Date weddingDay;
|
11 |
|
12 | uint8_t dayOfWeek( struct Date* date )
|
13 | {
|
14 | ...
|
15 | }
|
>
> Brauche ich da noch typedef - falls ja wo ?
ein typedef vereinfacht das ganze ein wenig, weil du damit aus einem
"struct Date" einen neuen Datentyp machen kannst
1 | struct Date
|
2 | {
|
3 | int day;
|
4 | int month;
|
5 | int year;
|
6 | };
|
7 |
|
8 | typedef struct Date Date_;
|
9 |
|
10 | Date_ birthDay;
|
11 | Date_ weddingDay;
|
12 |
|
13 | uint8_t dayOfWeek( Date_* date )
|
14 | {
|
15 | ...
|
16 | }
|
Du solltest ins Auge fassem, dir ein C-Buch zuzulegen. Deine Frage zeigt
ganz deutlich
* dass du kein Buch hast
* dass dir wesentliche Konzepte wie C funktioniert verständnismässig
noch nicht klar sind. Und zwar solche Konzepte, die dir jedes Buch
in 10 Minuten lesen näher bringt.
* Du verwendest die dicht gepackten Kurzformen, die dir C erlaubt,
ohne dir darüber klar zu sein, dass es sich um Kurzformen handelt
und wie die zugehörigen Langformen aussehen. Der normale Lernweg
ist aber genau anders herum. Erst lernt man die Langform und dann
lernt man, in welchen Fällen diese durch die kürzeren Formen
ersetzt werden können.
1 | struct SondenTel
|
2 | {
|
3 | uint16_t lfdNr; // 0 Einzelwert Zugriff ueber DatTxBuf.EinzelWert.lfdNr
|
4 | uint16_t Flow; // 1
|
5 | uint16_t Temp; // 2
|
6 | uint16_t Volt; // 3
|
7 | uint16_t iTmp; // 4
|
8 | uint16_t Leak; // 5
|
9 | uint16_t nc6; // 6
|
10 | uint16_t ChkSum; // 7
|
11 | };
|
12 |
|
13 | union TxArrayWortConverter // Union Name
|
14 | {
|
15 | int16_t WortArray[sizeof(struct SondenTel)]; // Arrayzugriff ueber Index mit DatTxBuf.WortArray[Index]
|
16 | struct SondenTel EinzelWert;
|
17 | };
|
18 |
|
19 |
|
20 | struct SondenTel Telegram1;
|
21 | struct SondenTel Telegram2;
|
22 | union TxArrayWortConverter DatTxBuf;
|
23 | union TxArrayWortConverter DatRxBuf;
|
24 |
|
25 |
|
26 | // oder mit typedef zur Verkürzung und Vereinfachung der Schreibweise
|
27 | typedef struct SondenTel SondenTel_;
|
28 | typedef union TxArrayWortConverter ArrayConverter_;
|
29 |
|
30 | SondenTel_ Telegram1;
|
31 | SondenTel_ Telegram2;
|
32 | ArrayConverter_ DatTxBuf;
|
33 | ArrayConverter_ DatRxBuf;
|
wie immer gilt:
Der Compiler liest den Text von oben nach unten. Und zwar nur ein
einziges mal. Bevor man etwas verwenden kann, muss es erst dem Compiler
bekannt gemacht werden. D.h. Ab dem Zeitpunkt an dem du den typedef
machst, kannst du dann im Text darunter überall anstelle von "struct
SondenTel" den durch den typedef dafür vereinbarten kürzeren Typnamen
"SondenTel_" benutzen.
Und das ist mit allen Dingen so: Erst dem Compiler bekannt machen, dann
benutzen. Und zwar von oben nach unten im Text.
Wenn du daher den typedef vorziehst, direkt hinter den Punkt an dem die
struct SondenTel bekannt ist, dann kannst du in weiterer Folge überall
den neuen Typnamen benutzen.
1 | struct SondenTel
|
2 | {
|
3 | uint16_t lfdNr; // 0 Einzelwert Zugriff ueber DatTxBuf.EinzelWert.lfdNr
|
4 | uint16_t Flow; // 1
|
5 | uint16_t Temp; // 2
|
6 | uint16_t Volt; // 3
|
7 | uint16_t iTmp; // 4
|
8 | uint16_t Leak; // 5
|
9 | uint16_t nc6; // 6
|
10 | uint16_t ChkSum; // 7
|
11 | };
|
12 |
|
13 | typedef struct SondenTel SondenTel_;
|
14 |
|
15 | union TxArrayWortConverter // Union Name
|
16 | {
|
17 | int16_t WortArray[sizeof(struct SondenTel)]; // Arrayzugriff ueber Index mit DatTxBuf.WortArray[Index]
|
18 | SondenTel_ EinzelWert;
|
19 | };
|
und weil das häufig so ist, gibt es dann die Möglichkeit, die
Strukturdefinition und den typedef zusammenzuziehen:
1 | typedef struct SondenTel
|
2 | {
|
3 | uint16_t lfdNr; // 0 Einzelwert Zugriff ueber DatTxBuf.EinzelWert.lfdNr
|
4 | uint16_t Flow; // 1
|
5 | uint16_t Temp; // 2
|
6 | uint16_t Volt; // 3
|
7 | uint16_t iTmp; // 4
|
8 | uint16_t Leak; // 5
|
9 | uint16_t nc6; // 6
|
10 | uint16_t ChkSum; // 7
|
11 | } SondenTel_;
|
12 |
|
13 | union TxArrayWortConverter // Union Name
|
14 | {
|
15 | int16_t WortArray[sizeof(struct SondenTel)]; // Arrayzugriff ueber Index mit DatTxBuf.WortArray[Index]
|
16 | SondenTel_ EinzelWert;
|
17 | };
|
und weil da jetzt der eigentliche Name der Struktur keine Rolle mehr
spielt, gibt es in C die Möglichkeit einer anonymen struct, d.h. einer
struct die keinen eigenen Namen mehr hat sondern nur noch über den
mittels typedef eingeführten Datentypnamen angesprochen werden kann:
1 | typedef struct
|
2 | {
|
3 | uint16_t lfdNr; // 0 Einzelwert Zugriff ueber DatTxBuf.EinzelWert.lfdNr
|
4 | uint16_t Flow; // 1
|
5 | uint16_t Temp; // 2
|
6 | uint16_t Volt; // 3
|
7 | uint16_t iTmp; // 4
|
8 | uint16_t Leak; // 5
|
9 | uint16_t nc6; // 6
|
10 | uint16_t ChkSum; // 7
|
11 | } SondenTel_;
|
12 |
|
13 | union TxArrayWortConverter // Union Name
|
14 | {
|
15 | int16_t WortArray[sizeof(struct SondenTel)]; // Arrayzugriff ueber Index mit DatTxBuf.WortArray[Index]
|
16 | SondenTel_ EinzelWert;
|
17 | };
|
genauso wie es häufig vorkommt, dass man bei der Definition einer struct
auch gleich Variablen mit erzeugen möchte
1 | struct SondenTel
|
2 | {
|
3 | uint16_t lfdNr; // 0 Einzelwert Zugriff ueber DatTxBuf.EinzelWert.lfdNr
|
4 | uint16_t Flow; // 1
|
5 | uint16_t Temp; // 2
|
6 | uint16_t Volt; // 3
|
7 | uint16_t iTmp; // 4
|
8 | uint16_t Leak; // 5
|
9 | uint16_t nc6; // 6
|
10 | uint16_t ChkSum; // 7
|
11 | };
|
12 |
|
13 | struct SondenTel Telegram1;
|
14 | struct SondenTel Telegram2;
|
C kommt dir da insofern entgegen, als man die Varieblendefinitonen
gleich an die Strukturdefinition anhängen kann und so zumindest an
dieser Stelle nicht alles 2 mal tippen muss:
1 | struct SondenTel
|
2 | {
|
3 | uint16_t lfdNr; // 0 Einzelwert Zugriff ueber DatTxBuf.EinzelWert.lfdNr
|
4 | uint16_t Flow; // 1
|
5 | uint16_t Temp; // 2
|
6 | uint16_t Volt; // 3
|
7 | uint16_t iTmp; // 4
|
8 | uint16_t Leak; // 5
|
9 | uint16_t nc6; // 6
|
10 | uint16_t ChkSum; // 7
|
11 | } Telegram1, Telegram2;
|
Alles über struct gesagte gilt sinngemäss genauso für union. Die beiden
unterscheiden sich in dieser Hinsicht syntaktisch nicht. Aus C Sicht
sind sowohl struct als auch union einfach nur Zusammenfassungen von
Daten, wobei eine struct die Dinge hintereinander und eine union die
übereinander anordnet. Aber wie diese Anordnung im Speicher ganz konkret
aussieht, darüber gibt dir der C-Standard keine Garantie. Der Compiler
hat da so einige Freiheiten.