Flexible Array Member initialisieren in C

Gast #7223527
Nabend,

ich habe da eine Frage, wie initialisiert man einen flexiblen array 
member zur Compilezeit ohne einen Roman zu schreiben?

Beispiel:
1
typedef struct
2
{
3
    const unsigned Anzahl;
4
    uint8_t Werte[];
5
} Muster_t;
6

7
Muster_t MusterA = { 3, { 0, 0, 0 } };
8
Muster_t MusterB = { 1000, { ... } };

In einfachen Fällen wie bei MusterA geht das ja noch, aber wenns mal 
mehr wird wie bei MusterB...
Achja, natürlich könnte ich auch den Speicher per malloc reservieren, 
nullen (bzw. calloc) und die Werte darauf umbiegen, aber das sollte doch 
irgendwie einfacher gehen.
Oder muss ich wirklich ein Script basteln was mir z.B. 1000 Komma 
separierte Nullen als String baut?
Und ja, mir ist schon klar, dass das statische Initialisieren von 
flexiblen array membern eigentlich nicht funktionieren sollte, aber der 
gcc macht da eh eine Ausnahme indem er den flexiblen member zu einem 
statischen macht mit der Größe der Anzahl der Initialisierungswerte.
Was dann natürlich auch eine Möglichkeit wäre, indem man selber für jede 
benötigte Größe des array member ein struct mit dem passenden statischen 
array baut; mit dem Ergebnis, dass man dann eventuell einen ganzen Zoo 
an structs hat.
Oder gibt es da noch eine andere Möglichkeit?

Ok, eine Möglichkeit wäre eventuell das Struct und das Array separat 
anzulegen und nur drauf zu pointern:
1
typedef struct
2
{
3
    const unsigned Anzahl;
4
    uint8_t *Werte;
5
} Muster_t;
6

7
uint8_t MusterA_Werte[3] = { };
8
uint8_t MusterB_Werte[1000] = { };
9

10
Muster_t MusterA = { sizeof(MusterA_Werte), MusterA_Werte };
11
Muster_t MusterB = { sizeof(MusterB_Werte), MusterB_Werte };
Aber schöner wird das alles nicht.
Beitrag #7223532 wurde von einem Moderator gelöscht.
Gast
Ein Skript, welches Dir Quellcode generiert? Oha, das klingt ziemlich 
abenteuerlich ;)

Was spricht denn dagegen, dass Du Dir eine Setup-Funktion schreibst, die 
das Array für Dich anhand der übergebenen Größe initialisiert?

Also statt
1
Muster_t MusterA = { 3, { 0, 0, 0 } };

zum Beispiel so:
1
Muster_t MusterA = setupMuster(3);
Gast
michi schrieb:
> Ein Skript, welches Dir Quellcode generiert? Oha, das klingt ziemlich
> abenteuerlich ;)

Noch nie eine diskrete Sinustabelle für die Verwendung in einem Array 
generiert oder ähnliches?

> Was spricht denn dagegen, dass Du Dir eine Setup-Funktion schreibst, die
> das Array für Dich anhand der übergebenen Größe initialisiert?
>
> Also statt
>
>
1
> Muster_t MusterA = { 3, { 0, 0, 0 } };
2
>
>
> zum Beispiel so:
>
>
1
> Muster_t MusterA = setupMuster(3);
2
>

Versuch doch einfach mal, nur so ungefähr, dir die Funktionsweise der 
setupMuster() Funktion zu überlegen...
Gast
michi schrieb:
> Was spricht denn dagegen, dass Du Dir eine Setup-Funktion schreibst, die
> das Array für Dich anhand der übergebenen Größe initialisiert?

Dagegen spricht, dass du nicht weißt, was ein flexible array member ist.
Gast
Schafft es der GCC, die Nullen wirklich zu Nullen oder kopiert er die?

Zudem ist es unschön, n manuell zu pflegen. Ich würde es separat machen.

Oder nur ein Array allokieren und die Struktur als Ptr darauf legen. Mit 
"init"Funktion, die den ptr zurückgibt,
1
 
2

3

4

5
Master_t *MasterPtrCreate(unsigned char *p, unsigned n)
6
{
7
Master_t *m = (Master_t *) p;
8

9
   m->Anzahl= n-sizeof m->Anzahl;
10

11
   return m;
12

13
}
14
...
15

16
void x(void)
17
{
18
static unsigned char buf[1234];
19

20
   Master_t *m=MasterPtrCreate(buf, sizeof buf);
21
   ...
22
}
Gast
Tim T. schrieb:
> Achja, natürlich könnte ich auch den Speicher per malloc reservieren,
> nullen (bzw. calloc)

anders geht es auch nicht.

und die Länge des Arrays kann man in der Struktur erst ablegen, wenn der 
Speicher für die Struktur (und das Array) reserviert wurde. Somit muss 
man die Größe des Arrays vorher kennen.
Gast
> Somit muss man die Größe des Arrays vorher kennen.

"Dank" VLA ist das nicht mehr noetig.
Ich persoenlich wuerde das in Verbindung mit Controllern
aber nicht als Gewinn ansehen.
Du kannst des mit designated-initializern initialisieren:
1
typedef struct {
2
    const unsigned Anzahl;
3
    uint8_t Werte[];
4
} Muster_t;
5

6
Muster_t MusterA = { 3, { 0} };
7
Muster_t MusterB = { 1000, {
8
                         [0] = 1,
9
                         [1] = 2,
10
                         [2] = 3,
11
                         [42] = 42
12
                     } 
13
                   };

Aber Achtung: hier gilt dann sizeof(Muster_t) == 2, was nicht der 
wirklichen Objektgröße entspricht.
DPA schrieb:
> Nö, c23 beschreibt immernoch überall, wie mit VLAs umzugehen ist. Sind
> also noch da.

Ich weiß nicht, auf was Du Dich beziehst. Aber was ich oben geschrieben 
habe, ist kein VLA, sondern ein array of unspecified size.
VLA kann man gar nicht initialisieren, sondern nur die Elemente 
zuweisen.
Moderator Persönliche Seite
ein lupenreiner Demokrat schrieb:
> und die Länge des Arrays kann man in der Struktur erst ablegen, wenn der
> Speicher für die Struktur (und das Array) reserviert wurde.
1
$ cat foo.c
2
struct foo {
3
        int length;
4
        char data[];
5
};
6

7
struct foo foobar = { .length = 42, .data = { 3, 10, 11, 0 } };
8
$ cc -Wall -Wextra -pedantic -O -S foo.c
9
foo.c:6:45: warning: flexible array initialization is a GNU extension [-Wgnu-flexible-array-initializer]
10
struct foo foobar = { .length = 42, .data = { 3, 10, 11, 0 } };
11
                                            ^
12
foo.c:3:7: note: initialized flexible array member 'data' is here
13
        char data[];
14
             ^
15
1 warning generated.
16
$ cat foo.s
17
        .text
18
        .file   "foo.c"
19
        .type   foobar,@object                  # @foobar
20
        .data
21
        .globl  foobar
22
        .p2align        2
23
foobar:
24
        .long   42                              # 0x2a
25
        .asciz  "\003\n\013"
26
        .size   foobar, 8
27

28
        .ident  "FreeBSD clang version 13.0.0 (git@github.com:llvm/llvm-project.git llvmorg-13.0.0-0-gd7b669b3a303)"
29
        .section        ".note.GNU-stack","",@progbits
30
        .addrsig

Also ja, man kann ein flexible array member standardgemäß so nicht 
initialisieren, nichtstandardgemäß geht es aber schon.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 4 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.