Forum: Compiler & IDEs Struktur mit Pointer "durchlaufen"


von Richard (Gast)


Lesenswert?

Hallo,

ich habe eine Struktur:
typedef struct {
byte a; // 1Byte
word b; // 2Bytes
byte c; // 1Byte
typ_irgendwas d; // 5Bytes
byte e[3]; // 3Bytes
} tStrukt;
tStrukt Strukt;

diese möchte ich genau in dieser Reihenfolge im Eeprom ablegen. (Falls
der Compiler die Struktur umsortieren würde, wäre das nicht schlimm, da
die Daten genauso wieder nach dem Powerup in die Struktur kopiert
werden sollen). Für das Eepromablegen habe ich eine funktionierende
Funktion Eep_write16Bytes(Adr, *daten16);

Ich habe mir gedacht einen Pointer über die Struktur laufen zu lassen
und das 16er Array "daten16" (byte daten16[16];) mit diesen Daten zu
befüllen.

for(i=0;i<sizeof(Strukt);i++)
{
  ...
  daten16[i]= ...;
}

1.) Ist meine Idee prinzipiell korrekt?
2.) Wie sind die "..." zu befüllen?
3.) Wie kann ich grundsätzlich auf das erste Element einer Struktur
zugreifen, wenn ich den Namen des Elements nicht kenne? (Grund: Ich
habe mehrere dieser Strukturen abzulegen und wieder zu restaurieren und
würde das gerne universell halten).

Gruß Richard.

von Joerg Wunsch (Gast)


Lesenswert?

Was spricht gegen die Verwendung von
eeprom_read_block()/eeprom_write_block()?

von Richard (Gast)


Lesenswert?

Hab ich da nicht auch das Problem, daß ich zuerst einen Puffer füllen
muß, der geschrieben werden soll?
Mir gings weniger um die Verwendung einer speziellen
Eeprom-Schreibroutine, sondern darum, wie ich das erste Element einer
Struktur "angreifen" kann, ohne den genauen Namen zu wissen.

Mit folgender Zuweisung (daraufhin zielte auch meine Frage 2 ab) habe
ich erfolgreich die Daten wegschreiben können:
for (i=0;i<16;i++)
  Daten16[i]=*(&Struktur.a+i);

Ich will aber zukünftig vermeiden (und darauf zielte Frage 3 ab :)),
daß das Element "a" explizit genannt werden muß. Sympatischer wäre
mir folgende (leider fehlerhafte) Zuweisung:
Daten16[i]=*(&Struktur+i);

(Meine Schwäche beim Verständnis von Zeigern usw. läßt sich natürlich
nicht verleugnen).
Wie wäre die korrekte Syntax?

Gruß Richard.

von Matthias (Gast)


Lesenswert?

Hi

ohne mir jetzt 100% sicher zu sein:

Daten16[i]=*((unsigned char *)(&Struktur+i));

Matthias

von Joerg Wunsch (Gast)


Lesenswert?

> Hab ich da nicht auch das Problem, daß ich zuerst einen Puffer
> füllen muß, der geschrieben werden soll?

Nein, aber Du brauchst eine typgleiche Variable im RAM von/zu der Du
kopieren kannst.

> ... wie ich das erste Element einer Struktur "angreifen" kann,
ohne
> den genauen Namen zu wissen.

Gar nicht.

> Ich will aber zukünftig vermeiden (und darauf zielte Frage 3 ab :)),
> daß das Element "a" explizit genannt werden muß. Sympatischer wäre
> mir folgende (leider fehlerhafte) Zuweisung:
> Daten16[i]=*(&Struktur+i);

Ich sehe nicht, was daran fehlerhaft sein sollte.

von Richard (Gast)


Lesenswert?

Ich hatte eher das Problem für ein AnsiC-Problem gehalten und deswegen
im GCC-Forum gepostet (und nicht unter allgemein), da ja der GCC auch
ein strenger AnsiC-Vertreter ist.

Ich verwende den Metrowerks Compiler für Motorola. Dieser meldet bei:
>  Daten16[i]=*(&Struktur+i);
Type mismatch (expected 'unsigned char ', given 'tStruktur ')

Aber inzw. hab ichs hinbekommen:
Daten16[i]=*((unsigned char *)(&Struktur)+i);
Sieht jetzt so ähnlich aus wie Matthias' Vorschlag, allerdings wird
jetzt nur noch die "Struktur" selbst gecastet (und nicht noch "+i"
gleich mit).

Kann jetzt leider nicht mit nem GCC vergleichen, dieser sollte(???)
aber doch den gleichen Fehler melden?

Vielen Dank für die Hilfen,
Gruß Richard.

von Hans (Gast)


Lesenswert?

welcher puffer muss warum gefüllt werden???

gib doch einfach dem eeprom-beschreib-befehl (char *)&structur als
pointer und sizeof(strukturdings) als bytelänge an... das funktioniert
prima und ohne gross herumtrixn zu müssn...


ich hab da z.b diese zeile bei mir verbastlt...

eeprom_read_block(&g_InputDevices[nCounter],(uint16_t *)
EEPROM_STRUCTURE_START+nCounter*INPUT_DEVICE_STRUCT_SIZE,
INPUT_DEVICE_STRUCT_SIZE);

ist zwar ein bisserl komisch aber wirst schon durchsteign ;)

73 de oe6jwf

von mthomas (Gast)


Lesenswert?

mglw. hilft auch eine "union", z.B.

struct Mystruct {
 unsigned short a;
 unsigned char b;
 unsigned char c[3];
};

union {
 Mystruct s;
 unsigned char arr[sizeof(Mystruct)];
} gConv;

void struct_to_eeprom(Mystruct *ps, unsigned int eeadr)
{
 gConv.s=*ps;
 eeprom_write_block(gConv.arr,&eeadr,sizeof(Mystruct));
}

Im Code mag der ein oder andere Syntaxfehler sein, aber im Prinzip
muesste es klappen (nicht getestet) und erscheint mir klarer. Methode
braucht etwas RAM, nicht zuletzte wg. der globalen "union", vermeidet
aber Probleme mit lokalen "Konverter-Unions" und deren zur Laufzeit
schlecht abschaetzbarem Platzbedarf.

von Richard (Gast)


Lesenswert?

> welcher puffer muss warum gefüllt werden???
gute Frage, eigentlich liegen die Daten ja schon im Speicher perfekt
bereit... (und die Daten ändern sich auch nicht während des Schreibens
- also eigentlich kein Problem).

Und die Sache mit der Union an sich ist auch ein guter Gedanke.

Ich werde meiner Eeprom-Schreibroutine einen Zeiger direkt auf die
Struktur übergeben - ganz ohne Puffer befüllen.

Danke für die Anregungen.
Gruß Richard.

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.