C - miért használják a nyilvánvalóan értelmetlen utasításokat a c-előfeldolgozó makrókban, miközben és ha-mással,
tennie. miközben és ha. mást. A makrót követően a pontosvessző mindig ugyanazt jelenti. Tegyük fel, hogy van valami, mint a második makró.
Most, ha a BAR-ot (X) kell használni; az if kifejezésben. mást. ahol az if nyilatkozat testjei nem voltak göndör fogantyúkba csomagolva, akkor meglepő lesz.
ami szintaktikailag helytelen, mivel máshol már nem kapcsolódik a ha. Ez nem segít átformálni a formákat göndör zárójelben belül egy makróban, mert a tekercses zárójelek után a pontosvessző szintaktikailag hibás.
A probléma két módon megoldható. Először vesszõt használj a makrón belüli sorrend kijelentésére, és nem véded meg a kifejezésmûködés képességétõl.
A fenti BAR változat verziója kiterjeszti a fenti kódot a következőre, amely szintaktikailag helyes.
Nem kell használnia. darabig. főzhetnél valamit, ha. mást. de ha igen. más fog bővülni, ha. különben "lefagy", ami még nehezebb lenne egy meglévő probléma megoldásához egy másik problémával, mint a következő kódban.
Az a pont, hogy pontosvesszőt használunk olyan környezetekben, ahol a hiba pontosvesszője hibás. Természetesen ezen a ponton (és valószínűleg) azt kell mondanod, hogy jobb lenne a BAR-t mint tényleges funkciót deklarálni, nem makrót.
Így van. Miközben meg kell találnod a C előfeldolgozó hátrányait, ha ezek a C-stílusú útmutatók elmondják, hogy eltávolítod a C előfeldolgozót, akkor aggódnak.
Három jó "tipp" van erre:
Segítsen a makrónak, mint egy valódi kód
A normál kód általában pontosvesszővel végződik. Ha a felhasználó olyan kódot lát, amelyre nincs szüksége.
Ez azt jelenti, hogy a felhasználó elvárja, hogy a fordító hibát generáljon, ha a pontosvessző hiányzik.
Ezért van olyan makró, amely félig kolóniát igényel.
Készítsen érvényes kódot
Amint az a jfm3 válaszban látható, néha egy makró több állítást tartalmaz. És ha a makrót az if utasításban használjuk, akkor problémás lesz:
Ez a makró telepíthető:
A g függvény a bIsOk értékétől függetlenül kerül végrehajtásra.
Ez azt jelenti, hogy hozzá kell adnunk egy makro körzetet:
2. érvényes kód létrehozása
Ha a makró valami hasonló:
További probléma lehet a következő kódban:
Mivel a következőképpen bővül:
Természetesen ez a kód nem fordul elő. Így ismét az megoldás használja a hatókört:
A kód ismét megfelelően viselkedik.
A hatások kombinációja egy csúszka + skálával?
Van egy C / C ++ nyelv, amely ezt a hatást produkálja: do / while loop:
A do / while művelet létrehozhat egy hatókört, így befogja a makró kódot, és végül szüksége van egy fél lapra a végén, így bővítve a kódot, amely megköveteli.
A C ++ fordító optimalizálja a do / while ciklust, mert az utóállapotának ténye hamis, a fordítási idő alatt ismert. Ez azt jelenti, hogy egy olyan makró, mint:
megfelelően bővül, mert
majd fordított és optimalizált
@ jfm3 - Jó válasz van a kérdésre. Azt is hozzá lehet adni, hogy a makró idiom is megakadályozza az esetleges veszélyesebb (mert nincs hiba) akaratlan viselkedés egyszerű "if" műveletek:
amely szintaktikailag helyes, ezért nincs fordító hiba, de valószínűleg véletlen következménye, hogy g () mindig nevezik.
A fenti válaszok megmagyarázzák ezeknek a konstrukcióknak a jelentését, de nincs köztük jelentős különbség. Valójában van ok, hogy kedveljék. mintha mintha. egyébként építeni.
Az építési probléma, ha. más, hogy nem kényszerít, hogy pontosvesszőt helyezzen el. Mint ebben a kódban:
Bár pontatlanul hagytunk egy pontosvesszőt, a kód tovább bővül
és automatikusan összeállítódik (bár egyes fordítók figyelmeztetést adhatnak a nem elérhető kódra). De a printf operátor soha nem fog végrehajtani.
tennie. Bár nincs ilyen probléma, mivel az egyetlen érvényes token után (0) pontosvessző.
Bár várható, hogy a fordítók optimalizálják a műveletet, miközben (hamis); hurkok, van egy másik megoldás, amely nem igényli ezt az építést. A megoldás a vesszőkezelő használatából áll:
vagy még egzotikusabb:
Bár ez jól működik a külön utasításokkal, nem fog működni azokkal az esetekkel, amikor változókat hoz létre és használ a #define részeként.
Ezzel használhatja a do / while konstrukciót.
A Jens Gustedt előfeldolgozói könyvtár (igen, az a tény, hogy létezik ilyen is, megrázta a fejem!) Javítja az if (1) másik konstrukciót egy kicsi, de jelentős módon, amely meghatározza a következőket:
Ennek oka az, hogy ellentétben a (0) -val. a szünet és a folytatás továbbra is a blokk belsejében dolgozik, de ((üres) 0) szintaktikai hibát generál, ha a makrókérés után a pontosvesszőt elhagyják, ami egyébként kihagyja a következő blokkot. (Valójában nincs probléma a "lógással", mivel a másik a legközelebbihez van kötve, ami a makróban van.)
Ha érdekli azokat a dolgokat, amelyek többé-kevésbé biztonságosan elvégezhetők a C előfeldolgozóval, nézd meg ezt a könyvtárat.
Néhányan helyi változókkal mutatott makrókat mutatott, de senki sem említette, hogy nem használhatsz semmilyen nevet a makróban! Egy napon harapni fogja a felhasználót! Miért? Mivel a bemeneti argumentumokat a makró sablonja helyettesíti. A makró példákban valószínűleg a leggyakrabban használt változó i nevet használja.
Például, ha a következő makró
a következő funkcióban használják
a makró nem fogja használni a feltételezett változót i, amelyet some_func elején deklaráltak, de a helyi ciklusban deklarált helyi változót. darabig.
Így soha ne használja a közös változók nevét egy makróban!
fogják lefordítani
észrevenni, hogy az i ++ értéket kétszer értékeljük egy makróban. Ez érdekes hibákhoz vezethet.
Jobban, mint csinálni <> míg (0) és ha (1) <> mást. csak használhatja (<>).
És ez a szintaxis kompatibilis a visszatérési értékekkel (do <> míg (0) nem, mint például:
Ezt a trükköt nagyon hasznosnak találtam olyan helyzetekben, amikor egy bizonyos értéket következetesen kell kezelnünk. A feldolgozás minden szintjén, ha van valamilyen hiba vagy érvénytelen állapot, elkerülheti a további feldolgozást és a korábbi menekülést. például