Forum: Mikrocontroller und Digitale Elektronik struct oder array wählen?


von Georg (Gast)


Lesenswert?

Halli,
ich stehe gerade vor einem Problem, bzw. einer Frage die mich grübeln 
lässt.

Ich habe ein Konstrukt vor mir das ich mir so vorstelle:
{ 0, { 9, 30, 1, 255, 1800 } }

Nun kann ich ja ein Array mittels [] initialisieren und später weitere 
Einträge hinzufügen / löschen. Nur klappt das mit dem Initialisieren als 
2D-Array bei mir irgendwie nicht. Und wenn ich das Array fest 
initialisiere als z.B int test[5][5] kann ich doch später keine weiteren 
Einträge hinzufügen ,oder?


Oder erstellt man nun ein struct like:
typedef struct
{
  uint8_t day;
  int *data;
} DATA_STRUCT;

Und lässt den pointer auf ein eindimensionales Array zeigen?

von Karl H. (kbuchegg)


Lesenswert?

Georg schrieb:
> Halli,
> ich stehe gerade vor einem Problem, bzw. einer Frage die mich grübeln
> lässt.
>
> Ich habe ein Konstrukt vor mir das ich mir so vorstelle:
> { 0, { 9, 30, 1, 255, 1800 } }
>
> Nun kann ich ja ein Array mittels [] initialisieren und später weitere
> Einträge hinzufügen / löschen.

Wo?
In C?

Nein.

> Nur klappt das mit dem Initialisieren als
> 2D-Array bei mir irgendwie nicht. Und wenn ich das Array fest
> initialisiere als z.B int test[5][5] kann ich doch später keine weiteren
> Einträge hinzufügen ,oder?

Das kannst du so nicht.
Arrays sind in C immer fix. Wenn sie erst einmal eine bestimmte Größe 
haben, dann haben sie die bis an ihr Lebensende. Wenn du dynamische 
Größenänderung brauchst, musst du in die dynamische Programmierung 
(malloc/free) rein. Oder aber, du kannst natürlich auch sagen: Das sind 
meine Maximalwerte, über die werde ich nie drüber kommen. Ich 
dimensioniere das Array auf Maximalgröße und benutze halt einige 
Einträge nicht.

> Oder erstellt man nun ein struct like:
> typedef struct
> {
>   uint8_t day;
>   int *data;
> } DATA_STRUCT;
>
> Und lässt den pointer auf ein eindimensionales Array zeigen?

Da erschliesst sich mir jetzt der Zusammenhang nicht ganz, den du da 
andeuten möchtest.

Vielleicht fängst du erst einmal ganz am Anfang zu erzählen an. Bei 
deinem eigentlichen Problem, welches du lösen möchtest und nicht bei dem 
Löungsversuch der dir Probleme bereitet.

von Georg (Gast)


Lesenswert?

Args, sorry....
WinAVR und nen mega168

das array soll halt datums / zeit-einträge halten

wobei die erste zahl den wochentag darstellen soll und der zweite 
eintrag, ein paar zeit-angaben. wenn ich nun z.B mit data[7][50] 
initialisiere, dann nutze ich schon sehr viel speicherplatz.

laut makefile vor einem test:
Data:        796 bytes (77.7% Full)
(.data + .bss + .noinit)

vorgesehen ist das man die werte mittels taster und lcds verändern kann, 
daher weiss ich nicht ob ich es vielleicht auch auslagern könnte ( 
PROGMEM ) und so wieder ein wenig speicherplatz einzusparen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> taster und lcds verändern kann,
> daher weiss ich nicht ob ich es auch auslagern könnte (PROGMEM )
Im Progmem kannst du nichts mehr ändern (oder nur mit viel Aufwand)...

von Karl H. (kbuchegg)


Lesenswert?

Georg schrieb:

> vorgesehen ist das man die werte mittels taster und lcds verändern kann,
> daher weiss ich nicht ob ich es vielleicht auch auslagern könnte (
> PROGMEM ) und so wieder ein wenig speicherplatz einzusparen.

Nein.
Das geht nicht (zumindest nicht simpel)
PROGMEM ist für dein Programm als absolut konstant und unveränderlich 
anzusehen. (Es gibt Ausnahmen, aber die sind sicherlich zu kompliziert).

Zum Problem:
Wenn du keine vernünftige Abschätzung machen kannst, bzw. mit dieser 
Abschätzung nicht leben kannst, weil sie zuviel Speicher verbraucht, 
dann wirst du wohl oder übel auf malloc/free ausweichen müssen, auch 
wenn man das eigentlich nicht möchte.

Die Anzahl der Tage ist ja fix, so wie ich das sehe. Die Woche hat nun 
mal nicht mehr als 7 Tage.
Also reicht es sich ein Array von 7 Pointern anzulegen, wobei jeder 
Pointer auf ein dynamisch allokiertes Array von Werten zeigt. Und 
natürlich muss es noch einen Mechanismus geben, der einem sagt, wieviele 
Einträge zur Zeit gerade allokiert sind.

Also sowas
1
struct Entry
2
{
3
  uint8_t nrAllocated;     // Anzahl momentan allokierter Einträge
4
  int*    Values;          // die Werte selber
5
};

Davon brauchst du 7 Stück, für jeden WOchentag einen
1
struct Entry Data[7];

Und du allokierst zb für Montag 3 Werte
1
#define MONDAY    0
2
#define TUESDAY   1
3
#define WEDNESDAY 2
4
#define THURSDAY  4
5
#define FRIDAY    5
6
#define SATURDAY  6
7
#define SUNDAY    7
8
9
void Init()
10
{
11
  uint8_t i;
12
13
  for( i = 0; i < sizeof(Data)/sizeof(*Data); ++i ) {
14
    Data[day].Values = NULL;
15
    Data[day].nrAllocated = 0;
16
  }
17
}
18
19
uint8_t Allocate( uint8_t day, uint8_t nrValues )
20
{
21
  struct Entry* newData = realloc( Data[day].Values, nrValues * sizeof( *Entry.Values ) );
22
23
  if( newData == NULL ) {     // Out of memory
24
        // tja. Was soll jetzt geschehen
25
    return FALSE;
26
  }
27
28
  Data[day].Values = newData;
29
  Data[day].nrAllocated = nrValues;
30
31
  return TRUE;
32
}
33
34
int main()
35
{
36
  Init();
37
38
  if( Allocate( MONDAY, 3 ) ) {
39
    // Allokierung erfolgreich
40
    Data[MONDAY].Values[0] = 28;
41
    Data[MONDAY].Values[1] = 56;
42
    Data[MONDAY].Values[2] = 178;
43
  }
44
45
  ....
46
47
  // Fuer Montag kommen noch 2 Werte dazu
48
  uint8_t sizeNow = Data[MONDAY].nrAllocated;
49
  if( Allocate( MONDAY, sizeNow + 2 ) ) {
50
    Data[MONDAY].Values[sizeNow] = 876;
51
    Data[MONDAY].Values[sizeNow + 1] = 23;
52
  }
53
54
  ...
55
56
  // Alle Werte für Montag
57
  for( i = 0; i < Data[MONDAY].nrAllocated; ++i )
58
    // mach was mit Data[MONDAY].Values[i]

von Georg (Gast)


Lesenswert?

Hey,
das ist mal ein Anstoss :) Nachdem ich heute den Tag über an zwei 
anderen Sachen schier schon fast verzweifelt bin, werde ich das gleich 
mal testen und schauen wie sich mein Speicher verhält :)

Bzw. ich muss dann mal durchrechnen wieviele Einträge ich machen kann.

Ich sage schon einmal im vorraus danke.

Gruss

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.