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