Forum: Mikrocontroller und Digitale Elektronik Struct zerlegen für Schleife


von Bernd F. (Gast)


Lesenswert?

Hallo,
ich benutze den gcc auf AVR, und meine C-Kenntnisse sind -ähm- 
ausbaufähig. Ich habe hier ein struct mit unterschiedlichen Wortbreiten, 
also etwa so:
1
typedef struct {
2
    uint8_t wert1;
3
    uint8_t wert2;
4
    uint32_t wert3;
5
    uint16_t wert4;
6
}my_struct;
7
my_struct daten;

Ich möchte nun die einzelnen Werte in eine Schleife bekommen, um eine 
Prüfsumme zu berechnen. Zwei Verständnisschwierigkeiten türmen sich vor 
mir. Wie bekomme ich Zugriff auf die einzelnen Werte, also etwa in der 
Art:
1
for(i=0;i<4;i++)
2
    {
3
        machmirdiePruefsumme(daten.wert[i]);
4
    }

Zum anderen, ich müsste wohl vermutlich zur Berechnung die struct-Werte 
auf 32bit casten. Wie müsste das aussehen?

Ihr seht schon, ich bin da etwas planlos. Hoffentlich habe ich mich 
zumindest verständlich ausgedrückt, und es gibt eine Lösung für die 
Sache.

Danke.

von Karl H. (kbuchegg)


Lesenswert?

Bernd F. schrieb:

> ausbaufähig. Ich habe hier ein struct mit unterschiedlichen Wortbreiten,
> also etwa so:
>
>
1
> typedef struct {
2
>     uint8_t wert1;
3
>     uint8_t wert2;
4
>     uint32_t wert3;
5
>     uint16_t wert4;
6
> }my_struct;
7
> my_struct daten;
8
>
>
> Ich möchte nun die einzelnen Werte in eine Schleife bekommen, um eine
> Prüfsumme zu berechnen.

Soll die Prüfsumme die Summe der Werte sein oder soll sie die Summe der 
Bytes sein.

> Zwei Verständnisschwierigkeiten türmen sich vor
> mir. Wie bekomme ich Zugriff auf die einzelnen Werte, also etwa in der
> Art:
>
1
> for(i=0;i<4;i++)
2
>     {
3
>         machmirdiePruefsumme(daten.wert[i]);
4
>     }
5
>

so gar nicht. Zumindest macht man das nicht so. Hängt aber auch darvon 
ab, was du unter Prüfsumme verstehst.

> Zum anderen, ich müsste wohl vermutlich zur Berechnung die struct-Werte
> auf 32bit casten.

Komtm drauf an, was du unter Prüfsumme verstehst.

> Wie müsste das aussehen?

> Ihr seht schon, ich bin da etwas planlos. Hoffentlich habe ich mich
> zumindest verständlich ausgedrückt, und es gibt eine Lösung für die
> Sache.

Kommt drauf an, was eigentlich genau das Problem ist. Fangen wir doch 
einfach mal damit an, was denn mit der Prüfsumme geschehen soll.
Wenn es sich um eine byteweise Prüfsumme handelt, die du zb irgendwohin 
übertragen musst, gibt es eine ganz einfache Lösung, indem man den 
Compiler zwingt die struct komplett zu ignorieren und den 
Speicherbereich einfach nur als Abfolge von Bytes anzusehen.

von klaus (Gast)


Lesenswert?

Hm, wenn du die Adresse der Struktur auf uint8_t* casten würdest, sehe 
ich das Problem, dass du die Prüfsumme auch über evtl. eingefügte 
Füll-Bytes berechnest. Du könntest das Alignment mit 
__attribute__((packed)) verhindern, allerdings dann alles GCC 
spezifisch. Ansonsten wirst du dir wohl die einzelnen Bytes mit 
Bitoperationen rausschneiden müssen, falls du für die 
Prüfsummenberechnen Bytes brauchst.

von Oliver J. (helmo2004)


Lesenswert?

Versuchs mal hiermit, obs funktioniert weiß ich nicht. Ist nur sone 
Idee.
1
    typedef struct {
2
    uint32_t wert1;
3
    uint32_t wert2;
4
    uint32_t wert3;
5
    uint32_t wert4;
6
}my_struct;
7
my_struct daten;
8
9
unit32_t *dat=&daten;
10
    
11
for(i=0;i<4;i++)
12
    {
13
        machmirdiePruefsumme(dat[i]);
14
    }

von Sym (Gast)


Lesenswert?

Man sollte die Struktur noch mit #pragma pack 1 packen und für die 
Schleifengrenzen unbedingt die sizeof()-Funktion verwenden. Prinzipiell 
sollte die Prüfsummenfunktion auf Basis von Bytes berechnen, da man 
ansonsten das Mischen mit kleineren Datentypen nicht korrekt ist.

von Bernd F. (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Kommt drauf an, was eigentlich genau das Problem ist. Fangen wir doch
> einfach mal damit an, was denn mit der Prüfsumme geschehen soll.

Das struct wird am Stück ins Eeprom geschrieben und von dort gelesen. 
Die "Prüfsumme" soll mir eventuelle Schreibfehler aufzeigen.
Wie die Prüfsumme genau aussieht, soweit war ich noch garnicht, ob das 
jetzt eine einfache Summe oder ein CRC wird. Ich lass' mich auch dazu 
gerne beraten.

Danke,
Bernd

von Peter D. (peda)


Lesenswert?

Du kannst ne Union machen aus der Struct und einem Bytearray und dann 
die CRC über das Bytearray bis sizeof(struct).
Um Paddingbytes zu vermeiden, zuerst die 32Bit, dann 16bit und dann 8Bit 
Variablen in die Struct packen.


Peter

von Thomas S. (tom72)


Lesenswert?

Ich würde das ganz einfach halten und keine Schleife verwenden.
1
machmirdiePruefsumme(daten.wert1);
2
machmirdiePruefsumme(daten.wert2);
3
machmirdiePruefsumme(daten.wert3);
4
machmirdiePruefsumme(daten.wert4);

von Rolf Magnus (Gast)


Lesenswert?

> Du kannst ne Union machen aus der Struct und einem Bytearray

Warum schlägt da eigentlich jeder gleich mit Unions um sich? Ein 
einfacher Zeigercast tut's auch.

> Um Paddingbytes zu vermeiden, zuerst die 32Bit, dann 16bit und dann
> 8Bit Variablen in die Struct packen.

Das spielt beim AVR keine Rolle, weil der eh keinerlei 
Alignment-Anforderungen hat.

von Peter D. (peda)


Lesenswert?

Thomas S. schrieb:
> Ich würde das ganz einfach halten und keine Schleife verwenden.
>
>
1
machmirdiePruefsumme(daten.wert1);
2
> machmirdiePruefsumme(daten.wert2);
3
> machmirdiePruefsumme(daten.wert3);
4
> machmirdiePruefsumme(daten.wert4);
5
>

Er will aber nur eine Prüfsumme und nicht 4.

Also Ziel verfehlt, 6, setzen.


Peter

von Udo R. S. (Gast)


Lesenswert?

@Peter: Nicht wenn die Funktion "machmirdiePruefsumme" den 
Prüfsummenwert auf eine globale Variable addiert. So war das wohl auch 
gemeint.

von Thomas S. (tom72)


Lesenswert?

Bernd hat oben in seinem Beispiel angegeben in welcher Art er die 
struct-Komponenten in der Schleife der Funktion übergeben möchte. Wie 
und wohin die Prüfsumme gerechnet wird??? - sorry steht da nicht. Also 
finde ich den Aufruf für jede Komponente immer gut.
Wenn ich die komplette Prüfsumme über alle Komponenten rechnen will 
brauch ich auch keine Schleife. Dann würde ich nen Zeiger auf die struct 
in der Funktion übergeben und die Prüfsumme zurückgeben.

tom

von Rolf Magnus (Gast)


Lesenswert?

> Bernd hat oben in seinem Beispiel angegeben in welcher Art er die
> struct-Komponenten in der Schleife der Funktion übergeben möchte. Wie
> und wohin die Prüfsumme gerechnet wird??? - sorry steht da nicht.

"Das struct wird am Stück ins Eeprom geschrieben und von dort gelesen.
Die "Prüfsumme" soll mir eventuelle Schreibfehler aufzeigen."

> Wenn ich die komplette Prüfsumme über alle Komponenten rechnen will
> brauch ich auch keine Schleife. Dann würde ich nen Zeiger auf die
> struct in der Funktion übergeben und die Prüfsumme zurückgeben.

Dann steht die Schleife halt in dieser Funktion.

von Michael H. (Gast)


Lesenswert?

Rolf Magnus schrieb:
> Wenn ich die komplette Prüfsumme über alle Komponenten rechnen will
> brauch ich auch keine Schleife. Dann würde ich nen Zeiger auf die struct
> in der Funktion übergeben und die Prüfsumme zurückgeben.

Mir ist nicht klar wie das auszusehen hätte. Könntest Du das genauer 
beschreiben?

von Karl H. (kbuchegg)


Lesenswert?

Michael H. schrieb:
> Rolf Magnus schrieb:
>> Wenn ich die komplette Prüfsumme über alle Komponenten rechnen will
>> brauch ich auch keine Schleife. Dann würde ich nen Zeiger auf die struct
>> in der Funktion übergeben und die Prüfsumme zurückgeben.
>
> Mir ist nicht klar wie das auszusehen hätte. Könntest Du das genauer
> beschreiben?

Die Schleife ist dann in der Funktion drinnen :-)
1
uint8_t CheckSumm( uint8_t * startByte, size_t size )
2
{
3
  uint8_t check = 0;
4
  size_t  i;
5
6
  for( i = 0; i < size; ++i )
7
    check += *startByte++;
8
9
  return startByte;
10
}

und aufgerufen wird es mit Umcasten der Adresse auf den Beginn der 
struct-Variablen
1
   ...
2
   summ = CheckSumm( (uint8_t*)&my_struct daten, sizeof( *my_struct daten ) );

von Thomas S. (tom72)


Lesenswert?

dito.
So wie Karl Heinz würde ich das auch machen. Vielleicht noch die 
Funktion mit nem const versehen um den Zeiger für Schreibzugriffe zu 
sperren
1
uint8_t CheckSumm( const uint8_t * startByte, size_t size )

von Peter D. (peda)


Lesenswert?

Udo R. S. schrieb:
> @Peter: Nicht wenn die Funktion "machmirdiePruefsumme" den
> Prüfsummenwert auf eine globale Variable addiert.

Wie unfein.
Dann fehlt aber noch das initialisieren dieser Variablen.

Ich mag mehrfache Aufrufe überhaupt nicht. Ich schreibe schon ne 
Schleife, wenn etwas nur zweimal ausgeführt wird.

Damit bin ich deutlich flexibler.
Laß mal in die Struktur noch weitere Elemente einfügen, dann mußt Du an 
der Schleife nix ändern, die läuft immer bis sizeof(struct).


Peter

von ... (Gast)


Lesenswert?

... wohl eher so:
1
uint8_t CheckSumm( uint8_t * startByte, size_t size )
2
{
3
  uint8_t check = 0;
4
  size_t  i;
5
6
  for( i = 0; i < size; ++i )
7
    check += *startByte++;
8
9
  return check;
10
}

von Karl H. (kbuchegg)


Lesenswert?

... schrieb:
> ... wohl eher so:

LOL

Danke für die Korrektur. Du hast natürlich recht

von Vlad T. (vlad_tepesch)


Lesenswert?

Ich würde zu

uint8_t CheckSumm( const void * start, size_t size )
{
  uint8_t * startByte = (uint8_t*) start;


tendieren und in der Funktion caste, so sehen die Aufrufe sauberer aus

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.