Makrot, pakotettu evaluointi
Tässä pätkä C -koodia:
#define add(j,k) (j k)
#define offset(elem) ( ( (PChar)&oma.elem ) - (p0) )
#define esize(elem) ( sizeof(oma.elem) )
#define einfo(elem) printf("'elem', %d, %d\n", offset(elem), esize(elem) );
void showIt()
{
BlobInfo oma;
PChar p0 = (PChar)&oma;
PChar _mapped = (PChar)&oma.mapped;
PChar _data = (PChar)&oma.data;
int x,y,z, xs,ys,zs;
x = _mapped - p0;
y = _data - p0;
z = 67;
x = offset(length);
y = offset(extent);
z = offset(quantum);
xs = esize(length);
ys = esize(data);
zs = esize(signature);
printf("x=%d y=%d z=%d ok.\n",x, y, z);
printf("xs=%d ys=%d zs=%d ok.\n",xs, ys, zs);
einfo(signature);
};
tuo viimeinen einfo(signature);
tulostaa tämän:
'elem', 24, 8
mutta tietenkin haluaisin sen tulostavan:
'signature', 24, 8
Eli miten pakotan tuon makron evaluoimaan tuon elem:n arvon myös (kaksinkertaisten) lainausmerkkienm sisällä ?
Tuossahan siis lainausmerkit ( " ) rajaavat merkkijonon ja heitomerkit ( ' ) on tarkoitettu olemaan osana tulostetta.
Tässä pätkä C -koodia:
#define add(j,k) (j k)
#define offset(elem) ( ( (PChar)&oma.elem ) - (p0) )
#define esize(elem) ( sizeof(oma.elem) )
#define einfo(elem) printf("'elem', %d, %d\n", offset(elem), esize(elem) );
void showIt()
{
BlobInfo oma;
PChar p0 = (PChar)&oma;
PChar _mapped = (PChar)&oma.mapped;
PChar _data = (PChar)&oma.data;
int x,y,z, xs,ys,zs;
x = _mapped - p0;
y = _data - p0;
z = 67;
x = offset(length);
y = offset(extent);
z = offset(quantum);
xs = esize(length);
ys = esize(data);
zs = esize(signature);
printf("x=%d y=%d z=%d ok.\n",x, y, z);
printf("xs=%d ys=%d zs=%d ok.\n",xs, ys, zs);
einfo(signature);
};
tuo viimeinen einfo(signature);
tulostaa tämän:
'elem', 24, 8
mutta tietenkin haluaisin sen tulostavan:
'signature', 24, 8
Eli miten pakotan tuon makron evaluoimaan tuon elem:n arvon myös (kaksinkertaisten) lainausmerkkienm sisällä ?
Tuossahan siis lainausmerkit ( " ) rajaavat merkkijonon ja heitomerkit ( ' ) on tarkoitettu olemaan osana tulostetta.
Vastaukset 11
Vanhimmat
En ole aivan varma haluatko tätä, mutta jos vastasin väärin, osaat selittää paremmin :-)
Jos jokin makron argumentti halutaan muuttaa merkkijonoksi, standardi-C:ssä voi käyttää preprocessorin (pp tästä lähtien) #-operaatiota.
Siispä seuraava makro ei muuta elem-arvoa miksikään, koska siihen ei viitata.
#define a(elem) printf("se on elem")
Tämä taas muuttaa argumentin merkkijonoksi. Huomaa, että se lisää itse "-merkit, joten niitä ei saa olla sen ympärillä.
#define b(elem) printf("se on " #elem)
Nämä toiminnassa:
-----------------
#include
#define a(elem) printf("se on elem")
#define b(elem) printf("se on " #elem)
int main (void){
a(makkara);
b(peruna);
return 0;
}
-----------------
Ajo:
se on elemse on peruna
Rivinvaihto mokoma unohtui! No, kuitenkin näet, että makkara ei mennyt läpi, mutta peruna meni.
Tuo risuaita parametrin nimen edessä siis ohjastaa PP:tä tekemään sen muutoksen merkkijonoksi, ja kääntäjä puolestaan näkee vain "-merkkien sisässä olevan merkkijonon, aivan kuin ohjelmoijan suoraan kirjoittaman. Peräkkäiset merkkijonot yhdistetään automaattisesti yhdeksi, joten risuaitaargumentteja voi latoa muun tekstin sekaan ilman ongelmia, kunhan lopullinen tulos on järkevä. Argumentin voisi siis ympäröidä puolilaunausmerkeillä vaikkapa näin:
"'" #elem "'..."
Missä ... on loput tekstistä.
PP ei saa katoa merkkijonojen sisään (määritelmän mukaan), joten sinne laitetut argumentin nimet eivät sitä hetkauta.
Sinulla on muuten einfo:n määritelmän lopussa mahdollisesti turha ;. Tämä ei ole vakava virhe, koska tuskin ahluat einfo:a käyttää esim. if-testin sisässä.
P
PP ei tietenkään osaa evaluoida tuota argumenttia itse mitenkään. Esim. b(3 5) siis tuottaa merkkijonon "3 5", eikä merkkijonoa "8" (edellisen viestin mukaisella määrittelyllä).
periaatteessa merkki siittä, että se koodaaja ei oo oikein jyvällä siittä, mitä sen niinkö alunperinkään olis siinä pitänny tehä?
Eivät ne ole. Makroja on aivan perusteltua käyttää, jos ne lyhentävät ja selkeyttävät koodia.
joita pitää käyttää selkiyttään sit koodii? Makrot on koodin selkiyttämismielessäkin helkkarin pahasta -sano mun sanoneen- ja niitä tulee käyttää äärimmäisessä hädässä ja vain ja ainoastansa pikapurkkakoodissa.
Makroilla on oma paikkansa eri yhteyksissä. On turhaa uhoamista väittää, että niiden käyttäminen on yksiselitteisesti pahasta. Esim. yleinen esimerkki makrosta, joka valitsee suuremman kokonaislukuargumenteistaan on varsin hyödyllinen ja selkeä kapistus. Vai pitäisikö sama koodinpätkä tunkea joka väliin? Tai ehkä tehdä aliohjelma sitä varten?
aina: inlinenä pelittää globaalisti ihan hyvin, kunhan muistaa kommentoida senkin koodin. Ei täällä mitään mesoamista ole. Pelkkiä faktoja vaan.
hiffaa nyt se ensin, sitten ehkä ymmärrät
Makrot harvoin selkeyttävät koodia. Niillä vaikutus on usemmiten aivan päin vastainen.
Makroja ei juurikaan pitäisi käyttää
;-)
tuo toinen tyypähdys tuskin on tehnyt yhtään toimivaa ohjelmaa helloworldin lisäksi.