Forum: Compiler & IDEs Array im EEPROM mit "variabler" Länge initialisieren


von Fabian (Gast)


Lesenswert?

Hallo Forum,
ich habe eine Frage zur initialisierung (zur Entwicklungszeit) eines 
EEPROMs. In meinem konkreten Fall geht es darum, dass ich ein Spiel auf 
einem AVR umsetze.
Die Anzahl der Spieler definiere ich mittels #define PLAYER_MAX, so dass 
ich diese je nach Auslastung des EEPROMs ggf. noch einfach anpassen 
kann. Außerdem programmiere ich ungerne mit "starren" Parametern.

Derzeit gehe ich von 16 Spielern aus.

Meine initialisierung des EEPROMs sieht aktuell so aus:
1
/* ************************************************************************** **
2
 * ** DEFINES
3
 * ************************************************************************** */
4
#define TOURNAMENT_INIT_PLAYER     {PLAYERTSTATE_OFF, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}
5
#define TOURNAMENT_INIT        {TOURNAMENTSTATE_FREE, {TOURNAMENT_INIT_PLAYER, \
6
  TOURNAMENT_INIT_PLAYER, \
7
  TOURNAMENT_INIT_PLAYER, \
8
  TOURNAMENT_INIT_PLAYER, \
9
  TOURNAMENT_INIT_PLAYER, \
10
  TOURNAMENT_INIT_PLAYER, \
11
  TOURNAMENT_INIT_PLAYER, \
12
  TOURNAMENT_INIT_PLAYER, \
13
  TOURNAMENT_INIT_PLAYER, \
14
  TOURNAMENT_INIT_PLAYER, \
15
  TOURNAMENT_INIT_PLAYER, \
16
  TOURNAMENT_INIT_PLAYER, \
17
  TOURNAMENT_INIT_PLAYER, \
18
  TOURNAMENT_INIT_PLAYER, \
19
  TOURNAMENT_INIT_PLAYER, \
20
  TOURNAMENT_INIT_PLAYER}}
21
22
/* ************************************************************************** **
23
 * ** LOCAL VARIABLES
24
 * ************************************************************************* */
25
tTournament eeTournament[] EEMEM = {TOURNAMENT_INIT, \
26
  TOURNAMENT_INIT, \
27
  TOURNAMENT_INIT, \
28
  TOURNAMENT_INIT};

Es werden also 4 Spielstände á 16 Spieler im EEPROM abgelegt.

Meine Frage ist nun, wie kann ich den o.g. Quelltext so dynamisieren, 
dass ich nicht 16x TOURNAMENT_INIT_PLAYER schreibe, sondern sich dies 
auf mein #define PLAYER_MAX bezieht?!

Vielen Dank im vorraus!

Fabian

PS: Die typdefs habe ich mir gespart zu posten, da es mir erstmal um das 
grundsätzliche Lösen eines solchen Problems geht.

von Uhu U. (uhu)


Lesenswert?

Da der Preprozessor keine Schleifen kann, mußt du dir ein #if-Gebirge 
bauen, das entsprechend der Definition von PLAYER_MAX die notwendigen 
Initialisierungen erzeugt.

Schön ist das nicht, aber es geht...

Die andere Möglichkeit wäre, dynamisch zu initialisieren.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Falls du gcc verwendest und keine keine Abneigung gegen GNU-C hast, geht 
ähnlich wie bei case-Ranges:
1
#define N 12
2
3
char c[N] = 
4
{
5
    [0 ... N-1] = 'a'
6
};

ansonsten gibt's noch die Möglichkeit, den Initializer in Assembler zu 
schreiben; der gas-Präprozessor kann mehr als der C-Präprozessor. Schau 
dir einfach mal .macro an. Damit kann man auch Schleifen machen und z.b. 
das i-te Element mit 2i initialisieren. Und dann gibt es noch .rept für 
einfache Fälle.

von Uhu U. (uhu)


Lesenswert?

Das wäre auch noch eine Möglichkeit für N <= 31:
1
#define N 11
2
 
3
char c[N] =
4
{
5
  #if N & 0x01
6
    "a"
7
  #endif
8
  #if N & 0x02
9
    "aa"
10
  #endif
11
  #if N & 0x04
12
    "aaaa"
13
  #endif
14
  #if N & 0x08
15
    "aaaaaaaa"
16
  #endif
17
  #if N & 0x10
18
    "aaaaaaaaaaaaaaaa"
19
  #endif
20
};

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Uhu Uhuhu schrieb:
> Das wäre auch noch eine Möglichkeit für N <= 31:
>
> [c]#define N 11
>
> char c[N] =
> {
>   #if N & 0x01
>     "a"
>   #endif
>   ...

Wenn's kein String ist, fehlen dann aber die trennenden Kommas.

Am einfachsten ist wohl, die Daten so auszulegen, daß sie Initializer 
überall 0 ist. Der obige Initializer sieht schon mal schwer danach aus.

von Uhu U. (uhu)


Lesenswert?

Johann L. schrieb:
> Wenn's kein String ist, fehlen dann aber die trennenden Kommas.

Das ist dank der Syntax für Initialisiererlisten auch kein Problem:
1
#define N 11
2
3
char c[N] =
4
{
5
  #if N & 0x01
6
    'a',
7
  #endif
8
  #if N & 0x02
9
    'a','a',
10
  #endif
11
  #if N & 0x04
12
    'a','a','a','a',
13
  #endif
14
  #if N & 0x08
15
    'a','a','a','a','a','a','a','a',
16
  #endif
17
  #if N & 0x10
18
    'a','a','a','a','a','a','a','a',
19
    'a','a','a','a','a','a','a','a',
20
  #endif
21
};

Ein Komma am Ende einer Initialisiererliste ist zulässig.

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.