Forum: Compiler & IDEs Funktion soll Zeiger auf Struct zurück liefern


von Christian J. (Gast)


Lesenswert?

Hallo,

ist sicher für viele trivial aber nicht, wenn man das noch nicht gemacht 
hat.

Ich habe eine Struktur vom Typ

typedef struct {
  byte  hour,
        min,
    alarms;
} __attribute__((packed)) logfile_t;

und einen Array, der aus einzelnen Elementen dieses Type besteht names 
logfile.

Ich möchte diesen Array nun aus einem EEPROM füllen und dabei wenn es 
geht die Funktion selbst als Rückgabewert benutzen. Also nicht wie im 
Beispiel unten eine Zeigerübergabe bei einer void Funktion.

Geht das überhaupt? Und wenn ja wie? Die 3 Bytes des Struct werden 
einzeln aus dem EE gefüllt.
1
/* Liest einen Alarm Datensatz aus dem externen EE aus */
2
void EE_ReadDataSet(logfile_t *ptr, uint16_t nr)
3
{
4
  char *p = (char*)ptr;
5
  uint16_t pos = (nr * sizeof(ptr));
6
  for (int i = pos; i < (pos + sizeof(ptr)); i++) {
7
    *p++ = eeprom.readByte(pos);
8
  }
9
}

Bisher.... hätte aber gerne *p = EE_ReadDataSet(i);
1
/* Externes EE auslesen ins RAM */
2
  logfile_t* p = logfile;
3
        for (int i = 0; i < logCnt; i++) {
4
         EE_ReadDataSet(p++,i);
5
}

von Christian J. (Gast)


Lesenswert?

Nur eine Vermutung, kann das derzeit nicht testen. Kompiliert aber 
durch.
1
/* Liest einen Alarm Datensatz aus dem externen EE aus */
2
logfile_t EE_ReadDataSet(uint16_t nr)
3
{
4
  logfile_t *res;
5
6
  uint16_t pos = (nr * sizeof(res));
7
  for (uint16_t i = pos; i < (pos + sizeof(res)); i++) {
8
      *(char*)res++ = eeprom.readByte(pos);
9
  }
10
  
11
  return (*res);
12
}

von mh (Gast)


Lesenswert?

Christian J. schrieb:
> Kompiliert aber
> durch.

Ohne Warnungen?

Christian J. schrieb:
> *(char*)res++ = eeprom.readByte(pos);

Es wird ein Byte aus dem EEPROM gelesen. Aber an welche Stelle im 
Speicher (RAM/Register) wird das Byte geschrieben?

von Christian J. (Gast)


Lesenswert?

mh schrieb:

> Christian J. schrieb:
>> Kompiliert aber
>> durch.
>
> Ohne Warnungen?
>
> Christian J. schrieb:
>> *(char*)res++ = eeprom.readByte(pos);
>
> Es wird ein Byte aus dem EEPROM gelesen. Aber an welche Stelle im
> Speicher (RAM/Register) wird das Byte geschrieben?

Das brachte den AVR dann auch zum Absturz, vermutlich weil es irgendwo 
hin geschrieben wurde, wo es nicht hin gehörte.

war inzwischen fleissig, das EE angeschlossen statt "trocken" zu 
programmieren, so funktioniert es. Geht sicher immer noch etwas 
optimaler, wenn man noch mehr castet. Aber der GCC fasst das ohnehin 
alles zusammen.

Denkfehler war auch dass sizeof(res) = 2 ist und nicht 3, wie erwartet. 
Also die Länge des Zeigers und nicht die worauf er zeigt.

1
/* Liest einen Alarm Datensatz aus dem externen EE aus */
2
logfile_t EE_ReadDataSet(uint16_t nr)
3
{
4
  logfile_t res;      // Ergebnis
5
  char *p = (char*)&res;    // Byte-Zeiger auf Ergebnis
6
  uint16_t pos = (nr * sizeof(logfile_t));
7
  
8
  /* Struct einzeln mit Bytes füllen */
9
  for (uint16_t i = pos; i < (pos + sizeof(logfile_t)); i++) 
10
    *p++ = eeprom.readByte(i);
11
  return (res);
12
}

von du brauchst immer speicher (Gast)


Lesenswert?

Christian J. schrieb:
> /* Liest einen Alarm Datensatz aus dem externen EE aus */
> void EE_ReadDataSet(logfile_t *ptr, uint16_t nr)
> {
>   char *p = (char*)ptr;
>   uint16_t pos = (nr * sizeof(ptr));
>   for (int i = pos; i < (pos + sizeof(ptr)); i++) {
>     *p++ = eeprom.readByte(pos);
>   }
> }

[c]
logfile *EE_ReadDataSet(logfile_t *ptr, uint16_t nr)
{
...
return ptr;
}

von du brauchst immer speicher (Gast)


Lesenswert?

Christian J. schrieb:
> logfile_t EE_ReadDataSet(uint16_t nr)
> {
>   logfile_t res;      // Ergebnis

neeee, pointer auf temporäre variable!

von Christian J. (Gast)


Lesenswert?

du brauchst immer speicher schrieb:
> logfile *EE_ReadDataSet(logfile_t *ptr, uint16_t nr)

Nope, kompiliert nicht, wenn man aus der Funktion einen Vektor macht.
Wenn dann logfile_t.

logfile_t *EE_ReadDataSet(logfile_t *ptr, uint16_t nr)

von Christian J. (Gast)


Lesenswert?

du brauchst immer speicher schrieb:
> neeee, pointer auf temporäre variable!

Also wie?

Das hier läuft ja.... und wie mit * ?

Oh... wurde ja schon geändert das Posting.... logfile_t *ptr braucht es 
aber nicht im Parametersatz. Ein Datensatz ist eindeutig zu finden über 
seine Nummer und hat die Adresse Nummer * Datensatzgröße.

von Christian J. (Gast)


Lesenswert?

Macht es eigentlich Sinn die Funktionen allgemein gültig zu halten und 
nicht an einen Typ zu binden?

Lässt sich der Hilfszeiger aus dem Cast

char *p = (char*)target;

noch mit dem

*p++ = eeprom.read(target++);

irgendwie verschmelzen?

Gibt ja die abenteuerlichsten * und ** und & Konstruktionen...

1
/* Schreibt einen undefinierten Struct weg */
2
void EE_Ext_WriteData(uint16_t target, void *source, size_t len)
3
{
4
  char *p = (char*)source;
5
  for (uint16_t i = 0; i < len; i++) {
6
    eeprom.write(target++, *p++);
7
  }
8
  
9
}
10
11
/* Beschreibt einen undefinierten Struct mit EE Daten */
12
void EE_Ext_ReadData (uint16_t eesrc, void *target, size_t len)
13
{
14
  char *p = (char*)target;
15
    for (uint16_t i = 0; i < len; i++) {
16
      *p++ = eeprom.read(target++);
17
    }
18
}

von x^y (Gast)


Lesenswert?

Christian J. schrieb:
> Macht es eigentlich Sinn die Funktionen allgemein gültig zu halten und
> nicht an einen Typ zu binden?

Wie immer: It depends. Hier im speziellen würde ich statt "void*" ein 
"uint8_t*" nehmen. Erstens, um klar zu machen, dass es Alignment und 
Padding zu beachten gilt wenn man die Funktion nutzt. Zweitens bezieht 
sich die Länge ja auf etwas und in diesem Fall auf Bytes, also uint8_t.

Die Write Funktion kann ein "const void*" Zeiger bekommen.

von Christian J. (Gast)


Lesenswert?

Danke,

ich kriege trotzdem noch die Flöhe, weil das falsche drin steht :-(((
Mann, so schwer ist das doch nicht. Das EE lässt sich einwandfrei 
beschreiben in for Schleifen. Das ist also schon mal ok. Aber der Rest 
ist Murks.
1
Aufrufe:
2
EE_Ext_WriteData(logCnt-1, (uint8_t*)&logfile[logCnt-1],sizeof(logfile_t));
3
      EE_Ext_ReadData(logCnt-1,(uint8_t*)&logfile[logCnt-1],sizeof(logfile_t));
4
5
6
/* Schreibt einen undefinierten Struct weg */
7
void EE_Ext_WriteData(uint16_t target, uint8_t *source, size_t len)
8
{
9
    for (uint16_t i = 0; i < len; i++) {
10
           eeprom.writeByte(target++, *(source++));
11
    }
12
}
13
14
/* Beschreibt einen undefinierten Struct mit EE Daten */
15
void EE_Ext_ReadData(uint16_t eesrc, uint8_t *target, size_t len)
16
{
17
       for (uint16_t i = 0; i < len; i++) {
18
          *(target++) = eeprom.readByte(i);
19
  }
20
}

Vorher:
19
8
17
Nachher:
19
19
19

von du brauchst immer speicher (Gast)


Lesenswert?

Christian J. schrieb:
> und dabei wenn es
> geht die Funktion selbst als Rückgabewert benutzen

Hast du deine Anfrage vergessen? Wo sind die Rückgabewerte?

Christian J. schrieb:
> Lässt sich der Hilfszeiger aus dem Cast
>
> char *p = (char*)target;
>
> noch mit dem
>
> *p++ = eeprom.read(target++);
>
> irgendwie verschmelzen?

Ja, typisiere source und target und lass p einfach weg.

Christian J. schrieb:
> char *p = (char*)target;
...
>       *p++ = eeprom.read(target++);

Überlege einmal genau was da passiert und welcher Wert in den Variablen 
steckt. :-<<<

Und gib bitte die Deklarationen der beiden eeprom. Funktionen an.

von Christian J. (Gast)


Lesenswert?

du brauchst immer speicher schrieb:
> Überlege einmal genau was da passiert und welcher Wert in den Variablen
> steckt. :-<<<

Habe die beiden schon umgeschrieben auf allgemein gültig, also struct 
unabhägig. Gibt immer noch murks. Sehe das Brett vor dem Kopf leider 
nicht.

von du brauchst immer speicher (Gast)


Lesenswert?

du brauchst immer speicher schrieb:
> Christian J. schrieb:
>> char *p = (char*)target;

was passiert hier?

Beitrag #5780033 wurde von einem Moderator gelöscht.
von x^y (Gast)


Lesenswert?

Christian J. schrieb:
> ich kriege trotzdem noch die Flöhe, weil das falsche drin steht :-(((
> Mann, so schwer ist das doch nicht. Das EE lässt sich einwandfrei
> beschreiben in for Schleifen. Das ist also schon mal ok. Aber der Rest
> ist Murks.

Also mich würde schonmal wundern, warum du "eesrc" gar nicht brauchst 
;-)

von Christian J. (Gast)


Lesenswert?

x^y schrieb:
> Also mich würde schonmal wundern, warum du "eesrc" gar nicht brauchst
> ;-)

Das Brett vorm Kopf.... :-) Wenn man zu lange davor sitzt....
1
/* Schreibt einen undefinierten Struct weg */
2
void EE_Ext_WriteData(uint16_t target, uint8_t *source, size_t len)
3
{
4
    for (uint16_t i = 0; i < len; i++) 
5
        eeprom.writeByte(target + i, *(source++));
6
}
7
8
/* Liest einen Struct mit EE Daten zurueck*/
9
void EE_Ext_ReadData(uint16_t eesrc, uint8_t *target, size_t len)
10
{
11
    for (uint16_t i = 0; i < len; i++)
12
       *(target++) = eeprom.readByte(eesrc + i);
13
}

von x^y (Gast)


Lesenswert?

PS: Mal die Warnungen einschalten?

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.