Práce se strukturami v C

Zdarec,
dnes jsem byl opět nemile překvapen.
Mějme strukturu s deklarací a definicí níže:[code]typedef struct
{
unsigned char SS;
unsigned char MM;
unsigned char HH;
unsigned char updated; // true when struct changed in interrupt
}time_t;

volatile time_t cas; // global[/code]
Dále funkci a její volání:[code]void casNaText(time_t tData, char *tstr)
{
// …
tData.updated = FALSE;
}

casNaText(cas, casText);[/code]
Toto nefunguje. Z proměnné (typu struktura, volatile) mohu pouze číst, změna se na původních datech neprojeví. Žil jsem doteď v desiluzi, že struktura je referenční datový typ a tedy stejně jako u pole se manipulace v ní projeví na původních datech. Očividně ne a celá struktura se patrně kopíruje jako primitivní datový typ.

Pokud to přepíšu na pointery, pracuje to správně ovšem s varováním o ztraceném kvalifikátoru (určitě volatile):[code]void casNaText(time_t *tData, char *tstr)
{
// …
(*tData).updated = FALSE; // funguje oboji
tData->updated = FALSE;
}

casNaText(&cas, casText);[/code]
Vím, že už jsem na to narazil(a jako dnes to vyřešil pointerem), ale teprve dnes jsem se nad tím nějak pozastavil.
Mohl by mi to někdo lehce osvětlit? Onu legendární knížku o C bohužel nevlastním :frowning:.

Druhá věc: lze zařídit přenos “volatile” i do funkce?

:arrow_right: administrator: přesunuto z "Ostatní"

No mne to pride ako normalne chovanie.
Ked urobis toto

void casNaText(time_t tData, char *tstr)
{
   tData.updated = FALSE;
}
casNaText(cas, casText);

Tak do funkcie natlacis dve premenne (nech su akekolvek, aj char alebo float), upravis ich a nikde nevratis - teda kompilator by urobil chybu ak by upravoval originalne data, pretoze si mu nikde nepovedal, aby tak urobil. Volanie funkcie s parametrami znamena vytvorenie novych premennych na stacku a tie sa upravuju, pripadne sa presuvaju na odovzdanie. Ak sa neupravuju, tak opustenim funkcie su nenavratne stratene a kompilator by ich mal podla spravnosti odoptimalizovat.

Jednou z moznosti ako tu urobit je to, ze ak si uz zadefinujes globalnu premennu, tak ju nedavat do parametrov, ale upravovat ju priamo, ako globalnu premennu. Cistejsie riesenie (co do programatorskej moralky) je urobit to cez pointery alebo urobit navratovy typ funkcie na time_t a returnovat tData.

Mě to tak úplně normální nepřišlo. Jméno struktury (nevím, kde jsem k tomu přišel) jsem pokládal za odkaz(= ptr) na její začátek (jako u pole). Očekával jsem tady chování pro takový objekt běžné.
Jeden zdejší kolega mě odkázal na písmo svaté a struktury se od ANSI C opravdu předávají hodnotou, pro odkaz je nutný pointer.

Teď jdu ještě zkoumat, jesli tam nenajdu něco o volatile parametru funkce.
Edit: O předávání volatile jsem se nedočet, ale snad stačí trochu přemejšlet.
Jelikož v C neexistuje volání odkazem, volá se vždy hodnotou. Pokud je parametrem funkce pointer, předá se jeho hodnota (adresa na kterou ukazuje). Pokud však jsou cílová data volatile, tak v tom stavu zůstávají, typový modifikátor chybí pouze u onoho pointeru. To má nejspíš následky, že pokud se během funkce změní původní předávaný pointer, tak míří jinam, než ten do funkce předaný. Důsledek bude, že pokud původní data zmizela (jsou neplatná), funkce bude pracovat s nesmysly. Zůstanou_li však cílová data na místě a jen se změní, funkce bude mít stále data aktuální.
Potřeboval-li bych mít volatile i předávaný pointer (např. u dynamicky alokovaných prvků), bylo by nutné vytvořit pointer na pointer jako parametr funkce a v ní se dle toho zařídit.
Nádhera :slight_smile:.
Z předchozího příkladu (struktura není dynamická) je tedy vhodný tento zápis (bez varování): casNaText((time_t *)(&cas), casText);