Preprocesszor makrók...

 ( wowbagger | 2010. január 4., hétfő - 13:56 )

Ez tipikusan az a téma, amihez nem értek annyira, ezért néztem bele az egyik levlistán az egyik levélbe, amiben egy srác kérdezte, hogy mit csinál a következő define, illetve a benne levő ___v:

#define readb(c) ({ __u8 __v = __raw_readb(__mem_pci(c)); __v; })

A következő választ kapta erre:

{} is a compound statement, () quotes it, and then you get one expression.
And the value of the expression is the last value of the compound statement.
so you can use readb like this:
alm_en = readb(base + S3C2410_RTCALM);
Here, read(..) is one expression, and you should add ";" after it.

Tehát, ha jól fordítom akkor ezt jelenti:

A {} egy összetett kifejezés, a () idézi?/egybefogja, és így egy kifejezést kapsz.
Így a readb-t a következőképpen használhatod:
alm_en = readb(base + S3C2410_RTCALM);
Itt a readb(..) egy kifejezés, ezért ";"-t kell utána írnod.

Nomármost, ettől nekem a dolog nem lett világosabb. El tudná magyarázni valaki, akinek több tapasztalata van ilyesmivel?

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Üdv!
Az összetett kifejezés, tulajdonképpen annyit takar, hogy ez a két utasítás, amikor behelyettesítődik, egy utasításként fog működni. Tehát ha te ezt pl: beteszed egy while törzsébe, akkor nem kell '{' '}' közé foglalnod pl:
while(1) valami=readb(c); helyesen fog működni. A közrefogás nélkül, a "__v;" utasítás kikerülne az while hatóköréből, ami érdekes hibákat proukálna. Itt pl olyasmit mondana a fordító, hogy a "__u8 __v" deklarácinak, nincs visszatérési értéke, amit a "valami" megkaphatna...
Közrefogással, tulajdonképpen egy kicsivel közelebb fog állni a makró használhatósága egy függvényhez.

__v egy változó. egy __u8 típusú változó, ami ha jól tudom, egy 8 bites unsigned int típust jelöl.
A "__v;" utasítás azért kell, hogy __v változó értéke legyen a kifejezés visszatérési értéke.

Azert egy dologra jo figyelni: ez a fajta makrozas/osszetett definicio nem resze az ansi/89-nek, igy ha hordozhatobb kodot csinalsz, akkor jo erre figyelni. A -Wall -std=c99 az mar teljesen jo.

Köszi, majd észben tartom!
De nem igazán vagyok oda a makrókért, ritkán használom. :P

Probald ki egy egyszerubb peldan:

#include <stdio.h>

#define add(a,b)        ({int c;c=(a)+(b); c;})

int main(int argc,char *argv[])
{
 fprintf(stdout,"sum of %d and %d is %d\n",10,20,add(10,20));
 return(0);
}

Akkor jo ez a megkozelites, ha olyan makrokat akarsz csinalni, amiben az operandusok kiertekelese nem trivialis. A fenti kicsit mesterkelt pelda, mert klasszikus makrozassal (#define add(a,b) ((a)+(b))) is meg tudod csinalni, ellenben pl ez:

#include <stdio.h>

#define funct(a,b)      ({int c,_a=(a),_b=(b);c=(_a+_b)*_a; c;}) 

int main(int argc,char *argv[])
{
 fprintf(stdout,"funct() is %d\n",funct(10,20));
 return(0);
}

Ekkor ha a funct() hasaban az elso parameterben ilyesmi kifejezes van, mint x++ (vagy ertekadas, vagy hasonlo), akkor a klasszikus makrozo megoldassal, azaz a

#define funct(a,b)   (((a)+(b))*(a))

sorral hibas eredmenyt/allapotot kapnal, mert az elso parametert ketszer inkrementalja. Ellenben a fentebbi funct() definicio jol fog mukodni.

__u8 az valami gcc tipus lehet, lenyegtelen, lehetne unsigned char is
__v az meg siman a valtozo neve __ azert van elotte, hogy nehogy utkozzon valami "rendes" valtozoval

--
NetBSD - Simplicity is prerequisite for reliability

Köszönöm a válaszokat. Valamelyest világosabb lett a dolog, bár még továbbra is ingoványos terepnek fog számítani a számomra.
-------------------------------------------------------------------------------
Az életben csak egy dolog a szép, de az épp nem jut eszembe.

Slackware Linux 12.1 | 2.6.26.7-janos

O", igen, annyi meg kimaradt, hogy:
- c-ben minden nem-nyelvi-utasitasnak azaz kifejezesnek van erteke. meg akkor is, ha nem hasznalod fel.
- utasitasok sorozatanak (amit a {...}-be teszel) is van erteke, az a sorozatbol a legutolso utasitas erteke.
- ezutobbi erteket ki tudod nyerni a rendszerbol, hogyha a {...}-t me'g egy, redundansnak latszo' (...) zarojellel korulveszed.

Ezutobbira egy extrem pelda:

a={42+137;1+2;};

vs.

a=({42+137;1+2;});

ezelobbi nem fordul le (error: expected expression before '{' token), mig ezutobbi megy sze'pen (leszamitva a standardokkal kapcsolatos figyelmezteteseket, i.e. az ansi/c89 nem ismeri ezt a szerkezetet. lasd feljebb valahol, irtam).

A makrozas (#define) meg lenyegeben csak me'g egy szint erre, de ezt a braced-groups within expression jatekot lehet csinalni #define nelkul is.

no, remelem igy ma'r nem maradt ki semmi :)

szerk: a nem-nyelvi-utasitas alatt vmi ilyesmire gondoltam, hogy ezt pl nem csinalhatod:

a=({if ( feltetel ) { 42; } else { 137; }});

ellenben ezt igen:

a=({int b;if ( feltetel ) { b=42; } else { b=137; } b;});

Elobbi peldaban egyetlen utasitas van a fo" {...}-ben, az egy if, annak nincs "erteke". Ezutobbi peldaban viszont az utolso utasitas egyben kifejezes is, annak van erteke, igy az megy ki.

Köszi, épp ebben a témában akartam új hsz-t írni.
A fentebbi hozzászóláskokban emlegetett makrókból kiindulva konstruáltam egy ilyet:

printf("What is the value of {int a; a=6+7; a;}? It is: %i\n", {int a; a=6+7; a;});

Ami nem fordult le. Aztán olvastam a hsz-odat, behelyettesítettem a következőre:

printf("What is the value of {int a; a=6+7; a;}? It is: %i\n", ({int a; a=6+7; a;}));

Ezek után rendben lefordult, és kiírja a beágyazott kódblokk értékét.
Ma is tanultam valamit. Köszi!

-------------------------------------------------------------------------------
Az életben csak egy dolog a szép, de az épp nem jut eszembe.

Slackware Linux 12.1 | 2.6.26.7-janos

xD

2010/1/3 Greg KH <greg_kroah.com>:
>> #define readb(c) ({ __u8 __v = __raw_readb(__mem_pci(c)); __v; })
>
> __v is an variable that the macro creates and then returns the value of.
>
> Don't code like this, it's horrible :)
>
> thanks,
>
> greg k-h
>
> --
> To unsubscribe from this list: send an email with
> "unsubscribe kernelnewbies" to ecartis_nl.linux.org
> Please read the FAQ at http://kernelnewbies.org/FAQ
>
>

-------------------------------------------------------------------------------
Az életben csak egy dolog a szép, de az épp nem jut eszembe.

Slackware Linux 12.1 | 2.6.26.7-janos