Funktion soll Zeiger auf Struct zurück liefern

Gast #5778867
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
}
Gast #5778889
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
}
Gast #5778946
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
}
Gast #5778948
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;
}
Gast #5779358
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
}
Gast #5779937
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.
Gast #5779999
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
Gast #5780006
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.
Beitrag #5780033 wurde von einem Moderator gelöscht.
Gast #5780084
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
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren