NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Anonymní statické pole ve statickém poli

V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Ghost07
Člen
Avatar
Ghost07:15.11.2022 19:43

Ahoj, jde v C vytvořit statické pole anonymních statických polí?
Momentálně to řeším dynamickou alokací, ale je to program pro embedded zařízení, a tam se doporučuje mít co možna nejvíc věcí alokovaných staticky.

Mám na mysli něco jako:

static void **config_values[] = {
    [CONFIG_TYPE_BOOL]   = (void *)[sizeof(uint8_t) * (CONFIG_PARAMETER_COUNT_BOOL)  ],
    [CONFIG_TYPE_INT]    = (void *)[sizeof(int)     * (CONFIG_PARAMETER_COUNT_INT)   ],
    [CONFIG_TYPE_FLOAT]  = (void *)[sizeof(float)   * (CONFIG_PARAMETER_COUNT_FLOAT) ],
    [CONFIG_TYPE_STRING] = (void *)[sizeof(char *)  * (CONFIG_PARAMETER_COUNT_STRING)]
};

Ale tohle skončí chybou: error: expected expression before ‘[’ token

Jakože, mohl bych nejdřív udělat normální proměnnou a pak do pole hodit její adresu:

void *config_bool_values[sizeof(uint8_t) * CONFIG_PARAMETER_COUNT_BOOL];
void *config_int_values[sizeof(int) * CONFIG_PARAMETER_COUNT_INT];
void *config_float_values[sizeof(float) * CONFIG_PARAMETER_COUNT_FLOAT];
void *config_string_values[sizeof(char *) * CONFIG_PARAMETER_COUNT_STRING];

static void **config_values[] = {
  [CONFIG_TYPE_BOOL] = config_bool_values,
  [CONFIG_TYPE_INT] = config_int_values,
  [CONFIG_TYPE_FLOAT] = config_float_values,
  [CONFIG_TYPE_STRING] = config_string_values,
};

Ale nevypadá to moc hezky a zbytečně zaberu 16 bajtů paměti (4 pointery po 4 bajtech), když pak ty proměnné podle jména stejně nebudu používat, ale budu k tomu přistupovat přes to pole.

 
Odpovědět
15.11.2022 19:43
Avatar
Ghost07
Člen
Avatar
Ghost07:15.11.2022 19:56

Aha, mám to :D

static void **config_values2[] = {
    [CONFIG_TYPE_BOOL]   = (void* [sizeof(uint8_t) * (CONFIG_PARAMETER_COUNT_BOOL)  ]) {},
    [CONFIG_TYPE_INT]    = (void* [sizeof(int)     * (CONFIG_PARAMETER_COUNT_INT)   ]) {},
    [CONFIG_TYPE_FLOAT]  = (void* [sizeof(float)   * (CONFIG_PARAMETER_COUNT_FLOAT) ]) {},
    [CONFIG_TYPE_STRING] = (void* [sizeof(char *)  * (CONFIG_PARAMETER_COUNT_STRING)]) {}
};
Akceptované řešení
+5 Zkušeností
Řešení problému
 
Nahoru Odpovědět
15.11.2022 19:56
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ghost07
DarkCoder:16.11.2022 16:22

Proč prostě nepoužiješ strukturu? :-D

Nahoru Odpovědět
16.11.2022 16:22
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Ghost07
Člen
Avatar
Ghost07:18.11.2022 11:54

A jo, struktura, dobrej point.

Myslím že jsem o struktuře taky přemíšlel, ale nejhorší bylo vymyslet, jak pojmenovat jednotlivé členy. Nemůžu je pojmenovat "bool", "int", "float", to jsou zakázaný slova :D Možná "type_bool", "type_int" atd.. ale to už začíná být dlouhý.

A další věc byla, že jsem chtěl na základě identifikátoru typu rovnou vybrat to správné pole s hodnotami - např. "config_values[ty­pe][idx * type_size]". Ale pak jsem zjistil, že abych s nima mohl nějak rozumně pracovat, tak musím stejně ukazatel void* přetypovat na ukazatel správného typu, aby to neházelo v kompilátoru varování při ukládání do jiné proměnné. Takže tam stejně musím mít nějaký switch, a tak je nakonec jedno jestli to budu mít ve 4 proměnných, nebo jedné struktuře se 4mi členy :D

Editováno 18.11.2022 11:55
 
Nahoru Odpovědět
18.11.2022 11:54
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Ghost07
DarkCoder:18.11.2022 12:29

Pojmenovat jednotlivé členy struktury už je to nejmenší (např. b_type, i_type). Srozumitelnost má větší váhu než délka identifikátoru.

Ano, void* je třeba před použitím přetypovávat na adekvátní typ. Dále pokud bys měl vše v jednom poli, musíš udržovat offsety jednotlivých částí. Vědět kde začíná sekce pro bool, kde pro int, atd. Zbytečně bys musel používat aritmetické operace pro přístup do odpovídající části pole.

a tak je nakonec jedno jestli to budu mít ve 4 proměnných, nebo jedné struktuře se 4mi členy

Není, neboť členy struktury jsou vedle sebe (pokud neberu v potaz padding). Na rozdíl od 4 samostatných polí, které mohou být v paměti rozhozeny různě. Máš tak větší šanci že si můžeš případně alokovat prostor pro větší souvislá data a alokace neselže. Ač jsou to 4 různá pole, mají k sobě určitou souvislost. Je tedy dobré je mít v rámci struktury. Deklarace struktury je o dost jednodušší. Práce s prvky struktury může být rovněž přehlednější. Struktura v tu chvíli funguje jako někdo kdo za ta pole zodpovídá.

Nahoru Odpovědět
18.11.2022 12:29
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Caster
Člen
Avatar
Odpovídá na Ghost07
Caster:19.11.2022 1:52

Podle mě na to jdeš s kanónem na vrabce. Programuji mj. MCU od Microchipu a tam se pro nastavení různých parametrů konfigurace používají struktury a konfigurační masky skupiny.

Např. ADC0.CTRLC &= ~(ADC_PRESC_gm); /* Clearing the prescaler bit field using a group mask */

Viz např. Microchip TB3262 AVR1000b: Getting Started with Writing C-Code for AVR® MCUs

 
Nahoru Odpovědět
19.11.2022 1:52
Avatar
Ghost07
Člen
Avatar
Odpovídá na DarkCoder
Ghost07:21.11.2022 13:39

DarkCoder:
Aha, to mě nenapadlo, tak struktura bude asi fakt nejlepší řešení no.

Caster:
My jsme to do teď tak nějak měli, že existovala struktura a jejími členy byly jednotlivé parametry. Ale tam jsi pak musel explicitně specifikovat konkrétního člena, když jsi chtěl uložit nějaký parametr nebo ho přečíst z NVS. A když pak chceš umožnit nastavovat parametry přes Modbus nebo webové rozhraní, tak musíš vždy vypsat všechny členy struktury, protože v C neexistuje foreach pro strukturu. To by šlo řešit mapou se seznamem klíčů a ukazatelem na konkrétního člena té struktury, ale to zabere zbytečné místo paměti - kvůli ukazatelům (v případě 50 parametrů 200 bajtů, jako... není to až tak moc jak jsem myslel, než jsem to teď spočítal :D ale stejně). Takže mi přišlo jako nejlepší udělat enumy a parametry rozházet do několika registrů/kontejnerů podle typu, tím se zbavím nutnosti mít na každý parametr v té mapě ukazatel.

Editováno 21.11.2022 13:40
 
Nahoru Odpovědět
21.11.2022 13:39
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 7 zpráv z 7.