Multi-dimensionale Arrays mit unterschiedlichen Größen in C

Gast #4788531
Lesenswert?

Hallo!

Ich würde gerne in C eine Abfolge von Befehlen für einen Betriebsmodus 
in einem Array zusammenfassen. Das Problem: Die Anzahl von und die Länge 
der einzelnen Befehlen variiert von Betriebsmodus zu Betriebsmodus.

Pseudocode, mit <n=?> für Anzahl die Anzahl der Bytes eines Befehls 
(BSP.: {0xDE, 0xAD, 0xBE, 0xEF} => {<n=4>}):
1
const uint8_t Steuerung_Befehl_AutomatikBetrieb[][] = {{<n=3>}, {<n=18>}, {<n=10>}};
2
const uint8_t Steuerung_Befehl_Betriebszustand_CROW[][] = {{<n=5>}, {<n=10>}, {<n=10>}{<n=16>}, {<n=21>}, {<n=28>}};
3
...

Wie bekomme ich das am Besten gelöst?

Danke und Grüße aus Bayern
Finn
Moderator (Firma: Titel) Persönliche Seite #4788542
Lesenswert?

DerBayer schrieb:
> Das Problem: Die Anzahl von und die Länge der einzelnen Befehlen
> variiert von Betriebsmodus zu Betriebsmodus.
Aber es gibt eine vordefinierte Maximalgröße?
Oder ist das Alles volldynamisch?

> Wie bekomme ich das am Besten gelöst?
Das geht am ehesten in Richtung "Union".
Damit wird über einen bestimmten Speicherbereich einfach eine "Maske" 
gelegt und der jeweilige Speicherinhalt einfach unterschiedlich 
interpretiert.

> Wie bekomme ich das am Besten gelöst?
Verhindere durch eine "geschickte" Befehlsstruktur das eigentliche 
Problem:
> Die Anzahl von und die Länge der einzelnen Befehlen
> variiert von Betriebsmodus zu Betriebsmodus.
Gast #4788565
Lesenswert?

Lothar M. schrieb:
> Aber es gibt eine vordefinierte Maximalgröße?
> Oder ist das Alles volldynamisch?

Maximalgröße? - Ja, sicherlich: 240 Bytes. Dennoch würde ich es mehr als 
volldynamisch bezeichnen.

Lothar M. schrieb:
> Das geht am ehesten in Richtung "Union".
> Damit wird über einen bestimmten Speicherbereich einfach eine "Maske"
> gelegt und der jeweilige Speicherinhalt einfach unterschiedlich
> interpretiert.

Da alles Variable ist hilft mir das nicht weiter. Und bei einer Union 
müsste ich auch auf irgendeine "Maske" zugreifen. Das heißt ich muss im 
Programmcode wissen was kommt ...

Lothar M. schrieb:
> Verhindere durch eine "geschickte" Befehlsstruktur das eigentliche
> Problem:
>> Die Anzahl von und die Länge der einzelnen Befehlen
>> variiert von Betriebsmodus zu Betriebsmodus.

Tja ... Das kann ich nicht ändern! Das "System" mit dem ich kommuniziere 
kommt ja nicht von mir bzw. "uns".

...

Mir ist nur ein Umweg über eine Struktur eingefallen. Das ganze kostet 
aber dann je Befehl 5 Byte mehr Speicher. Unschön!
1
#define MAKE_CMD_ENTRY(cmd)     { sizeof(cmd), cmd }
2

3
typedef struct
4
{
5
  const uint8_t  size;
6
  sonst uint8_t* cmd;
7
} CMD;
8

9
const uint8_t Steuerung_Befehl_A[] = {<n=3>};
10
const uint8_t Steuerung_Befehl_B[] = {<n=18>};
11
const uint8_t Steuerung_Befehl_C[] = {<n=10>};
12

13
const CMD Steuerung_Befehl_AutomatikBetrieb[] = { MAKE_CMD_ENTRY(Steuerung_Befehl_A), 
14
                                                    MAKE_CMD_ENTRY(Steuerung_Befehl_B), 
15
                                                    MAKE_CMD_ENTRY(Steuerung_Befehl_C) };

Gruß
Finn
Gast #4788567
Lesenswert?

vlt ein struct anlegen mit größe und pointer für den einzelnen befehl

wenn sich die befehle wiederholen eine einzelne liste anlegen mit den 
befehlen.
1
const uint8_t cmd1[]={..};
2
const uint8_t cmd2[]={.....};
3
...
4

5
typedef struct{
6
   const uint8_t len;
7
   const uint8_t *cmd;
8
}xxx_t
9

10
// modi 1
11
const xxx_t Steuerung_Befehl_AutomatikBetrieb[]={
12
 { 2 , cmd1},
13
 { 5 , cmd2},
14
 { 5 , cmd2}
15
}
16

17
// modi 2
18
const xxx_t Steuerung_Befehl_Betriebszustand_CROW[]={
19
 { 5 , cmd2},
20
 { 2 , cmd1},
21
 { 2 , cmd1}
22
}
#4788645
Lesenswert?

DerBayer schrieb:

> Da alles Variable ist hilft mir das nicht weiter.

So variabel ist es anscheint nicht, wenn du alle zu sendene Befehle im 
Flash legen kannst.

> Das heißt ich muss im
> Programmcode wissen was kommt ...

Du musst do sowieso wissen "was kommt", sonst würdest du nicht wissen 
welches Befehl zu senden ist?

> Tja ... Das kann ich nicht ändern! Das "System" mit dem ich kommuniziere
> kommt ja nicht von mir bzw. "uns".

Also:
- Wieviele von diesen Befehlen gibt es?
- Sind die zur Laufzeit konstant, oder enthalten sie variabele Teile?

> Mir ist nur ein Umweg über eine Struktur eingefallen. Das ganze kostet
> aber dann je Befehl 5 Byte mehr Speicher. Unschön!

? Nöh, doch nur 1 oder 2 bytes, je nachdem wie lange ein so ein Befehl 
sein kann.
1
// 1st element is length, rest is data
2
uint8_t cmd1[] = { 3, 0xF0, 0x0B, 0xAA };
3
uint8_t cmd2[] = { 245, 0x00, ... };
4
uint8_t cmd3[] = { 1, 0x02 };
5

6
void send(uint8_t cmd)
7
{
8
  for (uint8_t i = 1; i <= cmd[0]; i++)
9
    send_byte(cmd[i]);
10
}
11

12
...
13
    if(need_to_send_cmd1)
14
        send(cmd1);
15
    else
16
        send(cmd2);
17
...

EDIT: nur aufpassen wenn der Befehl 256 bytes lang ist :-)
Gast #4788652
Lesenswert?

@53453453454353:

Ähm ... Ist das nicht meine Lösung!?

Stromverdichter schrieb:
> Ich denke, du solltest dir mal das Thema "verkettete Listen" anschauen.
> vielleicht trifft das eher deinen Anwendungsfall

Glaube ich nicht. Wären dann sogar 9 Bytes, statt 5, da ich einen 
zusätzlichen Pointer sichern müsste:
1
typedef struct
2
{
3
  const uint8_t  size;
4
  const uint8_t* cmd;
5
  const CMD*     next;
6
} CMD;

Last but not least, sind verkettete Listen nur bei dynamischer 
Speicherallokierung von Nutzen. Nicht bei statischer ...
Gast #4788763
Lesenswert?

Eric B. schrieb:
> So variabel ist es anscheint nicht, wenn du alle zu sendene Befehle im
> Flash legen kannst.

Ja richtig. Die sind fest, ohne variablen Inhalt zur Laufzeit.

Eric B. schrieb:
> if(need_to_send_cmd1)
>         send(cmd1);
>     else
>         send(cmd2);

Ein aufeinanderfolgendes explizites Senden von Kommandos a la
1
send(cmd1);
2
send(cmd2);
will ich ja eben vermeiden.


Eric B. schrieb:
> EDIT: nur aufpassen wenn der Befehl 256 bytes lang ist :-)

Gibt es ja eben bei 8 Bit nicht ;-)

Peter D. schrieb:
>
1
char *cmd_str[] = { "Set", "Get", "Calib", "Info", "Uptime", "Reset", "Eestore", "" };

Lustig, dass das so funktioniert und mit einem Byte-Array nicht, obwohl 
es prinzipiell das selbe ist, denn "Set" ist ja ein Byte-Array 
{'S','e','t', 0}.

Dennoch geht das nicht:
1
const uint8_t* Steuerung_Befehl_AutomatikBetrieb[][] = {{<n=3>}, {<n=18>}, {<n=10>}};
#4788847
Lesenswert?

DerBayer schrieb:

> Eric B. schrieb:
>> EDIT: nur aufpassen wenn der Befehl 256 bytes lang ist :-)
>
> Gibt es ja eben bei 8 Bit nicht ;-)

Könnte man aber mit 0 kodieren.

>
> Peter D. schrieb:
>>
1
char *cmd_str[] = { "Set", "Get", "Calib", "Info", "Uptime", "Reset", 
2
> "Eestore", "" };
>
> Lustig, dass das so funktioniert und mit einem Byte-Array nicht, obwohl
> es prinzipiell das selbe ist, denn "Set" ist ja ein Byte-Array
> {'S','e','t', 0}.

cmd_str ist dan auch ein Array mit Pointern zu den Verschiedenen 
Texten.
Wäre also äquivalent zu
1
uint8_t cmd1 = { 'S', 'e', 't', 0 };
2
uint8_t cmd2 = { 'G', 'e', 't', 0 };
3
uint8_t cmd3 = { 'C', 'a', 'l', 'i', 'b', 0 };
4

5
uint8_t *cmds[] = { cmd1, cmd2, cmd3 ... };
#4788860
Lesenswert?

DerBayer schrieb:
> Ein aufeinanderfolgendes explizites Senden von Kommandos a la
>  send(cmd1);
>  send(cmd2);
> will ich ja eben vermeiden.

Wieso, weshalb und wozu? Irgendwann wirst du doch entscheiden müssen ob 
du cmd1 oder cmd2 schicken willst. Und wenn du mehrere cmd-s in Reihe 
schicken möchtest, dann eben so:
1
uint8_t *cmd_sequence1[] = { cmd1, cmd2, cmd3, 0 };
2
uint8_t *cmd_sequence_pi[] = { cmd3, cmd1, cmd4, cmd1, cmd5, 0};

oder über eine vararg-Funktion a la printf:
1
void send_cmds(uint8_t n, ...)
2
{
3
  va_list argp;
4
  va_start(n, argp);
5
  for(uint8_t i=0; i < n; i++)
6
    send(va_arg(argp, (uint8_t *)));
7
  va_end(argp);
8
}
9

10
...
11
send_cmds(3, cmd1, cmd2, cmd3);
12
send_cmds(5, cmd3, cmd1, cmd4, cmd1, cmd5);
Gast #4788895
Lesenswert?

Du kannst 0-terminierte Listen auch mit einem weiteren Sonderzeichen 
hierarchisch aufbauen. Beispiel: alle Befehle als Strings mit 0 
hintereinander, Ende ist wenn ein String mit 1 anfängt oder aufhört.
Vorteil: einfache Nutzung von stringroutinen, minimalster Overhead

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