Re: funkce v C - pro to nechod
Miroslav Mraz
mrazik na volny.cz
Středa Prosinec 30 13:27:38 CET 2015
Tu knihovnu pro EEPROM psal někdo, kdo to C++ docela dobře zná, takže je
to složeno z více objektů a jsou v tom různé finty. To je to, co se mi
platformě Arduino nelíbí. Pro uživatele je to dost jednoduché na
použití, pokud ví o co jde. Pokud to neví, pak je dost velká
pravděpodobnost, že to použije špatně. A čím jemnější jsou ty finty,
které se ale autoři snaží před uživatelem zakrýt, tím je tato
pravděpodobnost větší. Zde například metoda EEPROM::read() vrací jakoby
třídu EERef. Ale protože je návratová hodnota typu unsigned char, je
použita proxy metoda EERef::operator const uint8_t () const, takže použití
uint8_t x = EEPROM.read (5);
vyprodukuje takovouto sekvenci volání funkcí (metod)
EEPROMClass::read: 5
EERef::EERef: 5
EERef::operator const uint8_t: 5
EERef::operator*: 5
eeprom_read_byte : 0xAA << 5
takže vlastní čtení eeprom_read_byte() je někde až na 5. úrovni vnoření.
Ony ty metody jsou inline, takže se to patrně dost zoptimalizuje, ale
stejně mi to připadá dost neprůhledné. Ale pozitivněji. Protože je to v C++,
s instancí EEPROM třídy EEPROMClass lze pracovat jako s polem, takže
efektivněji můžeme psát
uint8_t x = EEPROM[5];
a místo EEPROMClass::read se pak volá EEPROMClass::operator[], jinak vše
zůstává. Stejně tak zapíšeme do EEPROM např.
EEPROM[5] = 0xAA;
Metody put() a get() umožňují zapsat / přečíst libovolný objekt, takže
lze napsat
int ofset = 10;
uint32_t z;
EEPROM.get<uint32_t> (ofset, z);
// v z je opravdu načtená hodnota - parametr předán referencí,
// což je pro C-čkaře poněkud neobvyklé
ale bude to správně fungovat jen tehdy, pokud byla data zapsána
předchozím voláním
z = cosi;
EEPROM.put<uint32_t> (ofset, z);
protože pro objekt se použije tolik bytů, kolik jich tento obsahuje,
tedy pro uint32_t 4. A jejich pořadí je dáno metodou.
Nicméně ty proxy metody jsem doposud nepoužil, nějak mi to uniklo, ale v
takhle nízkoúrovňovém programování je to docela užitečné i když dost
divné. Zase jsem se trochu něco naučil.
Mrazík
Dne 30.12.2015 v 00:26 Jan Waclawek napsal(a):
> Zacnem s tym, ze to je C++ a nie C.
>
> C++ presne nepoznam, ale je mozne, ze to spravanie v tomto konkretnom pripade je rovnake ako v C. Zakladom "problemu" je vsak urcite fakt, ze int je v avr-gcc aj
avr-g++ 16-bitovy. Neviem sice, aky je navratovy typ funkcie (pardon, ++
metody) co cita z EEPROM, ale tipujem, ze to bude jeden z troch
8-bitovych typov, co sa pred nasobenim vdaka usual arithmetic
conversions konvertuje na int. Rovnako konstanta 256 zo stredneho sucinu
je implicitne int, ergo aj ten sucin je typu int. Konstantny vysledok
pri inkriminovanej hodnote "stredneho parametra" nad 250 (a
pravdepodobne nad 128) je asi dana optimalizaciou vychadzajucou z faktu,
ze 128 a viac * 256 do [znamienkoveho 16-bitoveho] int pretecie, a teda
vysledok sucinu je nedefinovany, ergo moze byt aj nahodne cislo alebo aj
konstanta.
>
> Bolo by poucne vidiet relevantny disasemblat.
>
> wek
>
>
Další informace o konferenci Hw-list