Hallo,
ich habe ein Problem und hoffe Ihr könnt mir weiterhelfen. Ich habe ein
Tabelle, wo die Adressen von Parametern abgelegt sind. Es sind 8, 16 und
32-Byte-Parameter. Für die Definition der Tabelle habe ich die größten
Wert verwendet (32 Bit).
1
structknx_dp_def
2
{
3
UINT32u32_ID;
4
UINT8u8_Len;
5
UINT8u8_Sonder;
6
UINT32*p32_Parameter;// Zeiger auf Parameter
7
};
8
externstructknx_dp_defknx_dp[KNX_MAX_DP];
Damit der Compiler nicht meckert, habe ich vor jeder Variablen einen
Cast vorgesetzt (auch bei den 32-er Variablen - schadet ja nicht):
Soweit so gut. Nun will ich aber Werte in die entsprechenden Parameter
schreiben (in meinem Fall empfangene KNX-Daten). Damit ich weiß, wie
groß der Parameter ist, habe ich eine Längenangabe in der Tabelle
abgelegt (8, 16, 32). Die Info verwende ich auch, um den Wert
entsprechend zu casten:
Das funktioniert prinzipiell: aber der Zeiger verändert 32-Bit im RAM,
auch wenn ich 8 oder 16 Bit habe. Wie bringe ich den Zeiger dazu, dass
er nur 8 oder 16 Bit verändert? Geht das überhaupt irgendwie mit einem
Cast? Ich habe schon selbst herumexperimentiert, aber keine Lösung
gefunden. Mit Zeigern habe ich immer mal wieder etwas
Verständnis-Schwierigkeiten.
Gruß
Micha
Die C Zeigerwirtschaft ist sowieso schon recht gruselig.
Ein steter Quell besonderer Freuden.
Du machst es nicht besser, nur noch kritischer.
Mein Rat:
Keine falschen Zeigertypen verwenden!
Und wenn schon untypisierte Zeiger, dann doch bitte void Zeiger.
Du musst den Zeiger für den Zugriff selbst casten. Natürlich muss (je
nach Architektur) der Zeiger selbst passend ausgerichtet sein für die
jeweilige Objektgröße.
Sinnvoller wäre es, eine union aus Zeigern der unterschiedlichen Größen
zu machen und dann das passende union tag auszuwählen.
Sonstige Anmerkungen: uint8_t, uint16_t und uint32_t sind seit C99 mit
diesen Namen standardisiert. Benutze sie, statt eigene zu erfinden.
NULL ist seit Anbeginn standardisiert. Benutze es, statt eigene Namen zu
erfinden.
Die Fragwürdigkeit der "ungarischen" Notation ist hinlänglich diskutiert
worden. Deine Sache, ob du sowas trotzdem unbedingt brauchst.
Jörg W. schrieb:> Sinnvoller wäre es, eine union aus Zeigern der unterschiedlichen Größen> zu machen und dann das passende union tag auszuwählen.
Vielen Dank für den Tipp.
In meiner Tabelle kommen nun aber Warnungen bei allen definierten
Parametern, die mehr als 8 Bit haben (siehe Bild). Was muss ich da
angeben, damit es passt?
Micha schrieb:> Was muss ich da angeben, damit es passt?
Du musst das passende union tag initialisieren. Stichwort: named
initializers
Ich muss jetzt erstmal zum Mittagessen. :)
Micha schrieb:> Mit Zeigern habe ich immer mal wieder etwas> Verständnis-Schwierigkeiten.
Mach halt ein paar Inputs auf Nachfrage, dann bekommst du das schon
irgendwie mit.
Beim PC Asm muss man auch angeben, ob man einen Byte-Pointer oder einen
Word-Pointer haben will, wenn Daten aus dem Speicher gelesen werden.
Die zusätzlichen `{}` würde ich hier sehr empfehlen, das mögen die
Compiler, und macht alles etwas einfacher.
Zuletzt noch zur id. Stimmt dessen Wert mit dem Offset des Eintrags
überein? (also ist `uiDatapoint == knx_dp[uiDatapoint].id`?) Den dann
könnte man den aus `knx_dp_def` weg lassen:
Und zum Pointer, braucht es den Pointer wirklich? Falls der Pointer
mindestens 32bit braucht, und man in `knx_dp_def` einfach `uint32_t
parameter` nehmen würde, würde das sogar Speicherplatz sparen, und man
bräuchte keine Casts mehr.
Jörg W. schrieb:> Micha schrieb:>> Was muss ich da angeben, damit es passt?>> Du musst das passende union tag initialisieren. Stichwort: named> initializers
Du siehst schon, Weglassen der "ungarischen" Notation würde die Zeilen
etwas verkürzen …
1) Du kannst natürlich .parameter.ptr32=NULL explizit schreiben, aber
bei einer teilweisen Initialisierung einer struct werden implizit alle
nicht genannten struct tags eh mit 0 bzw. NULL bzw. 0.0 gefüllt,
insofern ist die Angabe dort unnötig, zumal in diesem Falle ja
"parameter" eh nicht ausgewertet werden wird.
Daniel A. schrieb:> Hier braucht es die klammern nun aber wirklich.
Stimmt, danke für die Korrektur.
Sinnvoll finde ich die Variante, die den Array-Index explizit benennt: