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.
- 1096 megtekintés
Hozzászólások
volatile nem segít ilyesmin?
- A hozzászóláshoz be kell jelentkezni
Na, de mi legyen volatile? Az interrupt handler függvény?
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
szerintem a ready / done változó
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
Az ( FNC, true ) az vessző operátor akar lenni? Nincs valami olyasmi, hogy kiértékelési sorrend?
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
Attól tekintsünk el, hogy a ready változó neve kifejezőbb volna, ha átnevezném done-ra. :)
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
Ezt ki kellene vizsgálni, hogy pontosan mire mondja és miért.
Hacsak az nem, hogy a INTERRUPT_test_and_run első három paramétere fordítási időben ismert, ezért tudja a fordító, hogy a FNC mindig meghívódik, és a ready már háromszorosan nemnulla a függvény végére, tehát a RESET hívására sosincs szükség.
Ebben az a esetben viszont az a kérdés, hogy mi másnak kellene történnie?
Szerk: a vesszőoperátornak nem az a szemantikája, hogy 'hajts végre a vessző utáni részt', hanem az, hogy 'hajtsd végre a vessző előtti részt (mellékhatásokkal együtt), azután hajtsd végre a vessző utáni részt, a kimenet ennek a második résznek az eredménye'.
Szerk2: most talán jobban értem, hogy kifejezetten a vesszőoperátorra vonatkozott a kérdés. Szerencsére az előző kiegészítésben ezt is leírtam; most csak annyit tennék hozzá, hogy a függvényhívásnál a paramétereket elválasztó vessző nem vesszőoperátor, vagyis a paraméterek kiértékelése tetszőleges sorrendben történhet, akár futásonként változhat (tehát ne építsünk arra, hogy pl. az előző futásnál balról-jobbra volt).
- A hozzászóláshoz be kell jelentkezni
Nem tudhatja. Ha engedélyezve van egy negyedik periféria, amelyik IT-t kér, akkor egyik maszkra sem lesz illeszkedés, és a végén a RESET()-nek kell futnia. Ha kiegyszerűsíthető lenne fordítási időben, nem írtam volna bele. Jó, tudom, rezeg a léc, mert alant NULL-ra vizsgálok, amikor sohasem hívom a függvényt NULL-al, de szerintem az azért úgy szép. :)
Igen, ez fontos kérdés. Tehát a vessző operátor esetén mindenképpen végre lesz hajtva a vessző mindkét oldalán található kifejezés? Akkor tehát mégis majdnem jó volt az eredeti makróm?
Igen, azt tudom, hogy függvényhívás esetén nem csinálhatom például ezt: fnc(x, x++); mert ennek csúnya vége lehet.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
> Ha engedélyezve van egy negyedik periféria, amelyik IT-t kér, akkor egyik maszkra sem lesz illeszkedés, és a végén a RESET()-nek kell futnia.
Off: Hát ezért lenne jó, ha az emberi olvasó meg tudná tippelné, hogy a PIE, PIR, MASK szimbolumok melyike #define-olt konstants, és melyike változó.
> Tehát a vessző operátor esetén mindenképpen végre lesz hajtva a vessző mindkét oldalán található kifejezés? Akkor tehát mégis majdnem jó volt az eredeti makróm?
Most zavarba jöttem, milyen lenne a "nem mindenképpen"? Mitől függene, hogy megcsinálja-e? (Jó, ha olyan speciális eset, hogy látja a fordító, hogy nincs mellékhatása, akkor lehet belőle egy 'useless calcluation' warning, de a függvényhívás az nem ilyen [bár ha a függvény is ugyanabban a source-ben van, és mondjuk üres a törzse, akkor akár ez is mehet].)
- A hozzászóláshoz be kell jelentkezni
A PIE az a regiszter abszolút címmel, amelyiknek az egyes bitjei egyes perifériák IT kérését engedélyezik. Azért kell makró, mert van egy rakás ilyen regiszter, hiszen 8 bites az MCU, de több, mint 8 IT-t kérő periféria van. A PIR az a regiszter, amelyben 1-be billen a PIE-vel azonos helyiértéken lévő bit, ha teljesül az IT kérés feltétele, például soros porton beérkezett egy karakter. Ez akkor is bebillen 1-be, ha amúgy a PIE által tiltva van az IT kérés, csak ez utóbbi esetben nem keletkezik megszakítás. Azért kell mégis összemaszkolni PIE-t és PIR-t, mert olyan is lehet, hogy egy másik periféria kér IT-t, amiatt megyünk bele ebbe az IT rutinba - itt csak egyetlen IT vektor van -, és ha PIE tiltottsága ellenére csak PIR-t vizsgálnánk, tévesen kiszolgálnánk az amúgy tiltott IT-jű perifériát.
A MASK pedig kiszedi azt a bitet, amelyik perifériához tartozik a PIE és PIR a nyolcból.
Zavarosan fogalmaztam. Olyasmire gondoltam, mint például az || vagy && operátorok esetében, hogy amikor már lehet tudni az eredményt, végre sem hajtódik a további része ezzel időt spórolva, de ezt például pointereknél vaskosan ki is használjuk:
char c, *p;
while (p && *p && *p != c) p++;
Tehát akkor a vessző operátor esetében mindkét oldal mindenképpen kiértékelésre, végrehajtásra kerül, ha jól értem.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Így van, a rövidzár kiértékelés a ||, &&, ?: operátorok specialitása, a vesszőoperátor szemantikája az, hogy mindig végrehajta mindkét oldalt.
Szóval az eredeti kérdést tovább kell vizsgálni, mire vonatkozik a compiler-warning.
- A hozzászóláshoz be kell jelentkezni
A sizeof operátor is érdekes:
[...] If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.
- A hozzászóláshoz be kell jelentkezni
Ez picit engem is zavarba tud hozni, hogy akkor most a tömb mérete, vagy pusztán a címének, egy pointernek a mérete, de az előbbi.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Várj, az más téma.
Az az egyik kérdés, hogy a sizeof kiértékeli-e az operandusát, vagy sem.
Az egy másik kérdés, hogy milyen környezetben konvertálódik a tömb típusú kifejezés a tömb első elemére mutató mutatóvá.
C99 6.3.2.1 Lvalues, arrays, and function designators, p3:
Except when it is the operand of the
sizeof
operator or the unary&
operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
- A hozzászóláshoz be kell jelentkezni
A VLA egy nagy... megkönnyítés, igen, azoknak a kedvéért, akiknek az alloca bonyolult.
#include <stdio.h>
int main(int argc, char **argv) {
int n= argc+3;
int a[n];
(void)argv;
printf ("sizeof=%d\n", (int)(sizeof a));
return 0;
}
Itt a sizeof
futásidőben kérdez le valamit, természetesen nem az a
elemeit, hanem az a
előtt lévő nem publikus metainformációt.
- A hozzászóláshoz be kell jelentkezni
Az alloca() nem szabványos (sem POSIX, sem ISO C; most legalábbis C11-ig próbáltam megnézni).
Én mondjuk semmilyen formában nem támogatom külső adattól függő méretű tömb foglalását "auto" tárolási osztályban (= vermen). Egyik írásmóddal (alloca vagy VLA) sem definiált, mi történik akkor, ha nincs elég hely.
C11-től kezdve egyébként opcionális a VLA támogatás; C11 6.10.8.3 Conditional feature macros:
The following macro names are conditionally defined by the implementation:
[...]
__STDC_NO_VLA__
The integer constant 1, intended to indicate that the implementation does not support variable length arrays or variably modified types.
- A hozzászóláshoz be kell jelentkezni
a vesszőoperátornak [...] az, hogy
Érdemes idézni a szabványból:
The left operand of a comma operator is evaluated as a void expression; there is a sequence point after its evaluation. Then the right operand is evaluated; the result has its type and value. [...]
Valamint
a függvényhívásnál a paramétereket elválasztó vessző nem vesszőoperátor
itt is (mivel ez példaként szerepel, ezért nem normatív, hanem informatív):
As indicated by the syntax, the comma operator (as described in this subclause) cannot appear in contexts where a comma is used to separate items in a list (such as arguments to functions or lists of initializers). On the other hand, it can be used within a parenthesized expression or within the second expression of a conditional operator in such contexts.
Ebben az a szép, hogy a szintaxis (a nyelv formális nyelvtana) diktálja, hogy a "," karakter mikor mi. A fenti paragrafus olyan függvényhívást mutat példának, hogy
f(a, (t=3, t+2), c)
azzal a kommentárral, hogy
the function has three arguments, the second of which has the value 5.
De ami igazán szép szerintem, az a második megjegyzés: within the second expression of a conditional operator. (Kiemelés tőlem.) Saját példáim:
int a[] = { 1 , 2 ? 3 : 4 };
int b[] = { 1 ? 2 , 3 : 4 };
int c[] = { 1 ? 2 : 3 , 4 };
Az "a"-nak az elemei: { 1, 3 }.
A "b"-nek az elemei: { 3 }.
A "c"-nek az elemei: { 2, 4 }.
A "b"-nél a nyelvtan alapján a vessző nem tudja "félbevágni" a feltételes operátor második operandusát, az "a"-ban lévő vesszőnél viszont a feltételes operátort még el sem kezdtük, a "c-"ben lévő vesszőnél pedig már befejeztük.
A "b"-nek a szintaxisfája:
conditional-expression
|
----------------------------------------------------+----------------------------------------
logical-OR-expression ? expression : conditional-expression
| | |
logical-AND-expression --------------------------+--------------- logical-OR-expression
| expression , assignment-expression |
inclusive-OR-expression | | ...
| assignment-expression ... |
exclusive-OR-expression | | 4
| conditional-expression 3
AND-expression |
| logical-OR-expression
equality-expression |
| ...
relational-expression |
| 2
shift-expression
|
additive-expression
|
multiplicative-expression
|
cast-expression
|
unary-expression
|
postfix-expression
|
primary-expression
|
constant
|
integer-constant
|
----------------+-------------------
decimal-constant integer-suffix(opt)
| |
nonzero-digit []
|
1
- A hozzászóláshoz be kell jelentkezni
Ezt a fát hogyan készítetted?
- A hozzászóláshoz be kell jelentkezni
Kézzel, NEdit-ben. Egyik ablakban a fát rajzoltam / írtam, a másikban nyitva volt a C99 szabvány. (Az egyes operátoroknál tárgyalja a helyettesítési szabályokat, de a végén az Annex A (informative) Language syntax summary tartalmaz összefoglalót is, ld. A.2.1 Expressions.) NEdit-ben nagyon jól lehet diagramokat rajzolni; fejlett támogatása van téglalap kijelölésére (lehet egérrel kijelölni, mozgatni, kivágni); van "fill selection with char" makrója (pl. ezzel lehet nagyon jól függőleges vonalakat húzni). Az Emacs nyilván többet tud, de én kb. 25 éve NEdit felhasználó vagyok.
- A hozzászóláshoz be kell jelentkezni
Most csinaltam egy ilyesmit:
$ cat x.c
#include <stdio.h>
static int funct(int x)
{
printf("x=%d\n",x);
return(0);
}
int main(void)
{
int a;
a=(funct(8),6*7);
printf("a=%d\n",a);
return(0);
}
$ gcc -Wall -pedantic -ansi -O3 -o x x.c
$ ./x
x=8
a=42
$ gcc --version
gcc (Debian 12.2.0-14) 12.2.0
$
Ezalapjan olyba' tunik hogy kiertekeli, akkor is hogyha nem hasznalja fel az eredmenyt.
- A hozzászóláshoz be kell jelentkezni
Köszönöm!
Akkor lehet, visszatérek a makrós megoldáshoz, bár a static inline függvény is majdnem makró, csak nem a preprocesszor helyettesít még szövegesen, hanem a fordító teszi az adott függvény törzsét a hívó helyre, ami kb. ugyanazt eredményezi szerencsés esetben.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
Mi ez a fordito egyebkent ha nem titok? `xc8` vagy barmi egyeb, gcc-alapu joszag?
- A hozzászóláshoz be kell jelentkezni
xc8, v2.50, PIC18F26Q71
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Akkor viszont ott lehetnek turpissagok :/ Az az egyetlen fordito ami a bitfieldeket sem ugy ertelmezi ahogy azt illendo. Siman lehet hogy ezt sem ugy csinalja ahogy a `gcc` es/vagy ahogy kellene.
Szoval ha barmiben bizonytalan vagy, akkor disassembly...
- A hozzászóláshoz be kell jelentkezni
Én inkább azt szoktam bizonytalanság esetén, hogy megkerülöm a problémát, és egy robusztus, mindenképp működő alakban írom le. Szerintem az inline függvényes megoldásomat nem tudja elszúrni, mert akkor már tényleg nem azt csinálja, ami oda van írva.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Hat, az `xc8` az a bitfield-eknel sem azt csinalta ami oda volt irva...
- A hozzászóláshoz be kell jelentkezni
Nem úgy van, hogy 0-ás bittől lefoglal annyit, amennyit kérsz, a következő field-del folytatja, és így tovább? Gondolom, ha a szószélességnél - pl. 8 vagy 32 bit - több esetén folytatja a következő 8 vagy 32 bites szavon, illetve szintén gondolom, hogy egy field belsejébe nem esik szóhatár.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
De, ez van ott is, 16-bites hatarokon. De mas 8-bites architekturan meg nincs ez. Meg ugye miert pont 16 biten ne loghatna at, miert nem 32 bit az, vagy 64 bit, vagy... vagy barhol atloghat. Marmint oke hogy a C standard megengedo, de akkor ugye elegge oda a hordozhatosag.
- A hozzászóláshoz be kell jelentkezni
Azért ha egy unsigned counter: 5; átlóg az architektúra bitszélességének határn, majd csinálsz egy var.counter++; utasítást, akkor abba megbolondul a fél világ, akkora kóddá fog fordulni. De optimális esetben is kivadássza a két címről a megfelelő biteket megfelelően összeillesztve, növeli, majd az eredmény megfelelő töredékeit az eredeti helyre pl. egy xor, and, xor-ral visszateszi. Ja, persze két helyre a két töredéket, előtte shiftelések is vannak.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
>,Marmint oke hogy a C standard megengedo, de akkor ugye elegge oda a hordozhatosag.
A micsoda van oda? A bitfieldek soha a fájó életben nem voltak hordozhatóak. Ja meg semmi más sem, ami nem a méretével osztható címen van (padding), vagy ami egynél több bájtból áll (endianness).
- A hozzászóláshoz be kell jelentkezni
Imigy?
#define INTERRUPT_test_and_run(ready,C1,C2,C3,funct) \
do \
{ if ( (C1)&(C2)&(C3) ) \
{ funct(); \
ready |= true; \
} \
} while(0)
void __interrupt() INTERRUPT_InterruptManager(void)
{
bool ready;
ready = false;
INTERRUPT_test_and_run(ready, PIE3, PIR3, _PIR3_TMR0IF_MASK, tmr0_isr);
INTERRUPT_test_and_run(ready, PIE4, PIR4, _PIR4_U1RXIF_MASK, rx_isr);
INTERRUPT_test_and_run(ready, PIE4, PIR4, _PIR4_U1TXIF_MASK, tx_isr);
if (!ready) RESET(); // unhandled interrupt
}
- A hozzászóláshoz be kell jelentkezni
Igen, ez jónak látszik. Annyi csak, hogy a ready |= true; az egyszerűbb ready = true; alakban. :)
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Egyébként miért szokás a do ... while(0) makróban? Valami sima ({ }) nem lenne megoldás? Persze lehet, le sem fordul.
Másik, amit sohasem próbáltam ki, hogy vajon a p->member helyett működne-e a (*p).member alak.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Egyébként miért szokás a do ... while(0) makróban?
Mert akkor csinalhatsz ilyet:
#define whatever(x) do { something(x);funct(x); } while(0)
/* ... */
if ( some_condition )
whatever(x);
else
something_else(x);
Egyebkent nem.
- A hozzászóláshoz be kell jelentkezni
Köszönöm. Nem gondoltam végig az összes lehetséges szintaxis esetét.
Szerinted a (*p).member működne a p->member helyett?
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Szerinted a (*p).member működne a p->member helyett?
$ cat x.c
#include <stdio.h>
struct obj
{ int memb;
} ;
int funct(struct obj *o)
{
printf("x=%d\n",(*o).memb);
return(0);
}
int main(void)
{
struct obj someobject;
(&someobject)->memb=6*7;
funct(&someobject);
return(0);
}
$ gcc -Wall -pedantic -ansi -O3 -o x x.c
$ ./x
x=42
$
Az mas kerdes hogy forditva csinalom es a obj.memb-ektol szabadulok es objptr->memb-eket hasznalok ahol csak lehet (azaz kb mindenhol :]).
- A hozzászóláshoz be kell jelentkezni
Arra utaltam, hogy noha kényelmes, jól olvasható a struktúrára mutató pointer tagja -> jelölés, lényegében redundáns. Bár, amikor a struktúra tag is pointer, ami mutat egy tagra, akkor nem volna túl jó ez:
(*(*p).ptr).member
Lényegesen jobban olvasható a p->ptr->member
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Elengedtem a makrót, végül ezt csináltam:
typedef void (*isr_t)(void);
static inline bool interrupt_test_and_run(uint8_t pie, uint8_t pir, uint8_t mask, isr_t isr) {
bool ret;
ret = isr && (pie & pir & mask);
if (ret) isr();
return ret;
}
void __interrupt() INTERRUPT_InterruptManager(void) {
bool done;
done = false;
done |= interrupt_test_and_run(PIE3, PIR3, _PIR3_TMR0IF_MASK, tmr0_isr);
done |= interrupt_test_and_run(PIE4, PIR4, _PIR4_U1RXIF_MASK, rx_isr);
done |= interrupt_test_and_run(PIE4, PIR4, _PIR4_U1TXIF_MASK, tx_isr);
if (!done) RESET(); // unhandled interrupt
}
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
- A hozzászóláshoz be kell jelentkezni
Itt mire gondolsz?
ret = isr && (pie & pir & mask);
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 :]
- A hozzászóláshoz be kell jelentkezni
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
- A hozzászóláshoz be kell jelentkezni
Újabb élmények. Megnéztem, mit fordít az xc8, de buta, pedig -O2. A static inline függvényt az inline ellenére nem mindannyiszor helyettesíti, hanem CALL-lal hívja, minekutána valóban a stack-en keresztül megvalósította a függvénypointeres hívást. Az egész felhajtás 212 byte-tal lett hosszabb - ha jól emlékszem -, mint a statikus megoldásnál, amikor is makróval a preprocessor helyettesít a fordítás előtt.
Szóval visszatértem a makrós megoldáshoz. Nem a 212 byte fáj igazán, hanem az interrupt rutin hatalmas overhead-je.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni
Es -O3?
- A hozzászóláshoz be kell jelentkezni
Úgy tudom, a -O3 és -Os nem free. Az xc32-ben már a -O2 sem free, bár ez most irreleváns.
tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE
- A hozzászóláshoz be kell jelentkezni