Forum: Mikrocontroller und Digitale Elektronik C > struct > flex Array


von Jan H. (janiiix3)


Lesenswert?

Nabend Community,

ich habe ein Array dessen Größe zur Kompilierung schon fest steht.
Ist es möglich das dem Kompiler mitzuteilen? Aktuell schmeißt er 
berechtigte Fehler "initialization of flexible array member in a nested 
context".

Es geht um "*pTim[]"
1
typedef struct
2
{
3
  TIMER_IRQ_t   IRQn;
4
  uint8_t      uiBitReg;
5
  uint8_t     uiSizeOfTims;
6
  TIM_TypeDef    *pTim[];
7
} TIMER_Irq_Cfg_t;
8
9
TIMER_Irq_Cfg_t sTimIRQnCfg[] =
10
{
11
    { TIMER_UPDATE_IRQ,        TIM_DIER_UIE,     7,{ TIM1, TIM3, TIM6, TIM14, TIM15, TIM16, TIM17   }},
12
    { TIMER_CAPTURE_COMPARE_1_IRQ,    TIM_DIER_CC1IE,  6,{ TIM1, TIM3, TIM14, TIM15, TIM16, TIM17       }},
13
    { TIMER_CAPTURE_COMPARE_2_IRQ,   TIM_DIER_CC2IE,  3,{ TIM1, TIM3, TIM15                 }},
14
    { TIMER_CAPTURE_COMPARE_3_IRQ,   TIM_DIER_CC3IE,  2,{ TIM1, TIM3                     }},
15
    { TIMER_CAPTURE_COMPARE_4_IRQ,   TIM_DIER_CC4IE,  2,{ TIM1, TIM3                     }},
16
    { TIMER_COM_IRQ,         TIM_DIER_COMIE,  4,{ TIM1, TIM15, TIM16, TIM17             }},
17
    { TIMER_TRIGGER_IRQ,       TIM_DIER_TIE,    3,{ TIM1, TIM3, TIM15                 }},
18
    { TIMER_BREAK_IRQ,         TIM_DIER_BIE,    4,{ TIM1, TIM15, TIM16, TIM17             }},
19
};

von Programmierer (Gast)


Lesenswert?

Das geht so nicht, weil jeder Eintrag des äußeren Arrays (sTimIRQnCfg) 
gleich groß sein muss; daher können die einzelnen 
TIMER_Irq_Cfg_t-Instanzen nicht unterschiedlich lange Arrays beinhalten.
Du musst jedes der Timer-Arrays als separate Variable anlegen und 
Pointer darauf verwenden. Eventuell lässt sich mit Makros & Statement 
Expressions (nur GCC) oder in C++ mit Lambdas etwas frickeln um das 
abzukürzen.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

da alles gleich groß sein muss, könnte man es mit Platzhalter auffüllen. 
Meistens mit 0 oder dem größten Wert des Wertebereiches. Hier mit 
Zeigern in C würde ich es mit NULL auffüllen. Sollte doch gehen?

Ich weiß nicht ob das in C im struct auch geht, Größe einfach festlegen.
1
TIM_TypeDef *pTim[7];

: Bearbeitet durch User
von Noch ein Kommentar (Gast)


Lesenswert?

Sollte mit zusätzlichen statischen Variablen klappen.
1
typedef struct
2
{
3
  TIM_TypeDef    *pTim;
4
} TIMER_Irq_Cfg_t;
5
6
TIM_TypeDef tmp1[] = {...}
7
TIM_TypeDef tmp2[] = {...}
8
...
9
10
TIMER_Irq_Cfg_t sTimIRQnCfg[] =
11
{
12
    { TIMER_UPDATE_IRQ,        TIM_DIER_UIE,     7, tmp1},
13
},

von Jan H. (janiiix3)


Lesenswert?

Veit D. schrieb:
> Hallo,
>
> da alles gleich groß sein muss, könnte man es mit Platzhalter auffüllen.
> Meistens mit 0 oder dem größten Wert des Wertebereiches. Hier mit
> Zeigern in C würde ich es mit NULL auffüllen. Sollte doch gehen?
>
> Ich weiß nicht ob das in C im struct auch geht, Größe einfach
> festlegen.TIM_TypeDef *pTim[7];

Ja das funktioniert. Nur werden da viele nützliche Bytes verschwendet, 
die an anderer Stelle mal fehlen könnten.

von Jan H. (janiiix3)


Lesenswert?

Noch ein Kommentar schrieb:
> Sollte mit zusätzlichen statischen Variablen klappen.
> typedef struct
> {
>   TIM_TypeDef    *pTim;
> } TIMER_Irq_Cfg_t;
> TIM_TypeDef tmp1[] = {...}
> TIM_TypeDef tmp2[] = {...}
> ...
> TIMER_Irq_Cfg_t sTimIRQnCfg[] =
> {
>     { TIMER_UPDATE_IRQ,        TIM_DIER_UIE,     7, tmp1},
> },

Danke!.

von Noch ein Kommentar (Gast)


Lesenswert?

> Nur werden da viele nützliche Bytes verschwendet,

Bei meinem Vorschlag auch. Für *pTim baut der Compiler einen 
zusätzlichen Pointer in die Struct ein. Eventuell brauchen die Pointer 
mehr Bytes als das pTim[7]. Und möglicherweise erzeugt der Compiler für 
den Zugriff über einen zusätzlichen Pointer auch noch zusätzlichen 
Maschinencode.

von Jan H. (janiiix3)


Lesenswert?

Ich habe gerade ein Problem beim Zugriff auf die Liste..
Musste das ganze mal bei pastebin.com Posten da hier die Formatierung 
nicht ganz passte (ja ich bin zu faul das hier alles zurecht zurücken)..

https://pastebin.com/MmiByfiW

Er greift auf die einzelnen Inhalte von TimList0..7[] nicht zu in Zeile 
30.

von Mombert H. (mh_mh)


Lesenswert?

Wieviel Warnungen liefert dein Compiler?

von Jan H. (janiiix3)


Lesenswert?

Mombert H. schrieb:
> Wieviel Warnungen liefert dein Compiler?

keine..

von Veit D. (devil-elec)


Lesenswert?

Hallo,

bau einmal serielle Debugausgaben ein. Zum Bsp. für Irq und 
sTimIRQnCfg[i].IRQn um den Vergleich zu überprüfen ob der überhaupt 
gültig werden kann. Ich vermute ein Problem mit der Zeiger 
Dereferenzierung bzw. fehlender dieser, weil die TIMs sind doch 
Registeradressen? Nicht das es eine Verwechslung mit Adresse und 
Addressinhalt gibt. Kann auch die Parameterübergabe sein ... . Wie man 
es macht wird es verschiedene Möglichkeiten geben, es muss nur 
einheitlich sein. Soviel zu meiner Vermutung.

von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

Veit D. schrieb:
> Hallo,
>
> bau einmal serielle Debugausgaben ein. Zum Bsp. für Irq und
> sTimIRQnCfg[i].IRQn um den Vergleich zu überprüfen ob der überhaupt
> gültig werden kann. Ich vermute ein Problem mit der Zeiger
> Dereferenzierung bzw. fehlender dieser, weil die TIMs sind doch
> Registeradressen? Nicht das es eine Verwechslung mit Adresse und
> Addressinhalt gibt. Kann auch die Parameterübergabe sein ... . Wie man
> es macht wird es verschiedene Möglichkeiten geben, es muss nur
> einheitlich sein. Soviel zu meiner Vermutung.

Das habe ich schon gemacht mit dem CubeIDE Debugger.
Wenn ich das richtig interpretiere greift er auf die Listen[0..7] aber 
auf deren Inhalte nicht. Anbei mal ein Foto.

von Programmierer (Gast)


Lesenswert?

Ehm, dass du bei "( TIM_TypeDef* )TimList7" casten musst ist doch sehr 
verdächtig - da ist was faul!

Wenn du es genau wie in

Noch ein Kommentar schrieb:
> Sollte mit zusätzlichen statischen Variablen klappen.

geschrieben machst, brauchst du keinen Cast. Bei "if ( pTim == 
sTimIRQnCfg[Index].pTim + IndexTimList )" brauchst du auch keinen.

Insbesondere musst du pTim als gewöhnlichen Pointer definieren:
1
typedef struct
2
{
3
  TIM_TypeDef    *pTim;
4
} TIMER_Irq_Cfg_t;

von Jan H. (janiiix3)


Lesenswert?

Programmierer schrieb:
> Ehm, dass du bei "( TIM_TypeDef* )TimList7" casten musst ist doch
> sehr
> verdächtig - da ist was faul!
>
> Wenn du es genau wie in
>
> Noch ein Kommentar schrieb:
>> Sollte mit zusätzlichen statischen Variablen klappen.
>
> geschrieben machst, brauchst du keinen Cast. Bei "if ( pTim ==
> sTimIRQnCfg[Index].pTim + IndexTimList )" brauchst du auch keinen.
>
> Insbesondere musst du pTim als gewöhnlichen Pointer definieren:typedef
> struct
> {
>   TIM_TypeDef    *pTim;
> } TIMER_Irq_Cfg_t;

Habe ich ja gemacht. Wenn ich das so mache..

https://pastebin.com/VX86fb5n

Wirft er mir: "(near initialization for 'sTimIRQnCfg[1].pTim')"

von Programmierer (Gast)


Lesenswert?

Ach jetzt hab ich mich selber durcheinander gebracht, die Tiger sind ja 
Pointer... Versuch es mit "struct { TIM_TypeDef **pTim; }". Casts 
sollten da jedenfalls nirgendwo sein.

Jan H. schrieb:
> (near initialization for 'sTimIRQnCfg[1].pTim')"

Das ist übrigens nur ein kleiner Fetzen der eigentlich Fehlermeldung.

von Jan H. (janiiix3)


Lesenswert?

Programmierer schrieb:
> Ach jetzt hab ich mich selber durcheinander gebracht, die Tiger
> sind ja
> Pointer... Versuch es mit "struct { TIM_TypeDef **pTim; }". Casts
> sollten da jedenfalls nirgendwo sein.
>
> Jan H. schrieb:
>> (near initialization for 'sTimIRQnCfg[1].pTim')"
>
> Das ist übrigens nur ein kleiner Fetzen der eigentlich Fehlermeldung.

Du hast Recht. Es muss ja ein "Zeiger auf den Zeiger sein".
Danke! Funzt.

: Bearbeitet durch User
von Programmierer (Gast)


Lesenswert?

Jan H. schrieb:
>>
>
> Du hast Recht. Es muss ja ein "Zeiger auf den Zeiger sein", war doch so
> oder?

Ja genau.

Jan H. schrieb:
> Wie wird dieser gleich noch referenziert?

Der äußere Zeiger muss in der schleife dereferenziert werden. Mir fällt 
gerade auf dass die auch angepasst werden muss. Bin noch nicht ganz wach 
🤦‍♂️:
1
if ( pTim ==  sTimIRQnCfg[Index].pTim[ IndexTimList])

Der innere Zeiger wird überhaupt nicht dereferenziert, nur verglichen.

von Jan H. (janiiix3)


Lesenswert?

Programmierer schrieb:
> Jan H. schrieb:
>>>
>>
>> Du hast Recht. Es muss ja ein "Zeiger auf den Zeiger sein", war doch so
>> oder?
>
> Ja genau.
>
> Jan H. schrieb:
>> Wie wird dieser gleich noch referenziert?
>
> Der äußere Zeiger muss in der schleife dereferenziert werden. Mir fällt
> gerade auf dass die auch angepasst werden muss. Bin noch nicht ganz wach
> 🤦‍♂️:
> if ( pTim ==  sTimIRQnCfg[Index].pTim[ IndexTimList])
>
> Der innere Zeiger wird überhaupt nicht dereferenziert, nur verglichen.

Alles gut ist ja auch Montag :D
Ich habe ihn schon dereferenziert ;).

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.