Nézzük az alábbit:
#define INTERRUPT_test_and_run(PIE, PIR, MASK, FNC) (((PIE) & (PIR) & (MASK)) ?\
(FNC, true) : false)
void __interrupt() INTERRUPT_InterruptManager(void) {
bool ready;
ready = false;
ready |= INTERRUPT_test_and_run(PIE3, PIR3, _PIR3_TMR0IF_MASK, tmr0_isr());
ready |= INTERRUPT_test_and_run(PIE4, PIR4, _PIR4_U1RXIF_MASK, rx_isr());
ready |= INTERRUPT_test_and_run(PIE4, PIR4, _PIR4_U1TXIF_MASK, tx_isr());
if (!ready) RESET(); // unhandled interrupt
}
Gondolhatja-e a fordító, hogy a RESET() hívásához szükséges ready változó helyes előállításához szükségtelen a makróban hivatkozott FNC meghívása? Mert ha ezt gondolja, akkor épp az interrupt handlert fogja kispórolni, és sovány vigasz lesz annak a néhány byte-nak a megspórolása. :) Veszélyes-e ebből a szempontból ez a makró?
Szerk.: Nem azt állítom, hogy most rosszul fordítja - még nem próbáltam ki -, hanem az a kérdés, hogy vajon ez egy annyira ügyetlen makró, amitől állandóan ott a fejem felett a pallos, hogy egyszer csak kispórolja a fordító az IT handler hívását, vagy ez így teljesen jó, netán teljesen rossz, vagy picit módosítani kellene rajta?
Megjegyzés:
Annak, aki esetleg érdekesnek gondolja, úgy tűnik, az eredeti makró - itt fentebb - hibás, s a fordító nem érzi szükségesnek a vessző operátor előtti függvény hívását, hiszen a kifejezés anélkül is kiértékelhető. Akkor viszont nem hívódik az interrupt handler.
Hozzászólások
volatile nem segít ilyesmin?
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
Na, de mi legyen volatile? Az interrupt handler függvény?
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
szerintem a ready / done változó
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
Azt szerintem ki kell számítania, mert különben nem tudná a végén, hogy reset legyen, vagy sem. Itt az a bajom, hogy az (FNC, true) az az FNC hívása nélkül is true, tehát FNC hívása elhagyható a kifejezés eredményének szempontjából, viszont épp az FNC a katarzis ebben a dologban. :)
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
Az ( FNC, true ) az vessző operátor akar lenni? Nincs valami olyasmi, hogy kiértékelési sorrend?
tl;dr
Egy-két mondatban leírnátok, hogy lehet ellopni egy bitcoin-t?
Igen, vessző operátor. Ezt láttam oda a legalkalmasabbnak. Balról jobbra, és a leggyengébben „köt”.
Szerk.: Csak ugye FNC nélkül is tudható, hogy (FNC, true) az true, tehát nem kell FNC-t hívni. Szóval sajnos ez így nem jó, már látom.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
Attól tekintsünk el, hogy a ready változó neve kifejezőbb volna, ha átnevezném done-ra. :)
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
Részben megvan a válasz:
warning: (759) expression generates no code
Szomorú vagyok, át kell alakítani. Az előbb nem vettem észre, csak most. :(
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
Egyre kevésbé értem. Ha az a ready volatile, akkor nem ad a fordító warningot azzal, hogy a kifejezésből nem fordult kód, viszont byte-ra pontosan ugyanolyan hosszúságú kód fordul. Másfelől, ha nem is hívja FNC-t, a kifejezést szerintem nem spórolhatja le, ellenben honnan tudhatná, hogy a végén kell-e a RESET() hívása, vagy sem? Azt elhiszem, hogy FNC hívást kispórolja, de a kifejezést muszáj lenne kiértékelnie.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
Imigy?
Igen, ez jónak látszik. Annyi csak, hogy a ready |= true; az egyszerűbb ready = true; alakban. :)
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
Elengedtem a makrót, végül ezt csináltam:
Kérdés, hogy a függvénypointer átadásánál rájön-e arra, hogy ez fordítási időben eldől, mert már akkor tudható a cím, és közvetlenül egy hívássá fordítható mindenféle futásidejű címszámítás nélkül.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
Itt mire gondolsz?
mi az isr szerepe a feltetelben? hogy ne legyen NULL? de ha NULL akkor minek is hivod meg? :)
Egyebkent sztem ki fogja optimalizalni a fordito, de gyorsan ke tudod ellenorizni :]
Igen, néha szoktam beleírni efféle védelmeket. NULL ellen van. :) Már csak azért is, mert sok függvényemet írom meg úgy, hogy ha kérek tőle valamit, akkor átadom a változó címét, ha nem, akkor NULL-t adok meg neki, persze ettől nem borul fel:
int8_t valami(uint16_t *var) {
if (var) *var = kifejezés;
return 0;
}
uint16_t result;
valami(NULL);
vagy
valami(&result);
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE