do. în timp ce și dacă. altceva. Pentru a face punct și virgulă după macro-ul tău înseamnă întotdeauna același lucru. Să presupunem că ai ceva de genul celui de-al doilea macro.
Acum, dacă trebuie să utilizați BAR (X); în expresia dacă. altceva. în cazul în care corpurile declarației if nu au fost înfășurate în bretele coite, veți obține o surpriză proastă.
care este incorect sintactic, deoarece altceva nu mai este asociat cu dacă. Acest lucru nu ajută să înfășurați formele în bretele cotite în interiorul unei macrocomenzi, deoarece punct și virgulă după bretele curl este incorect sintactic.
Există două modalități de remediere a problemei. Mai întâi, utilizați o virgulă pentru afirmația secvenței din interiorul macrocomenzii, fără ao proteja de capacitatea de a acționa ca o expresie.
Versiunea de mai sus a barei BAR extinde codul de mai sus la următoarea, care este corect din punct de vedere sintactic.
Nu trebuie să utilizați. în timp ce. ai putea să gătești ceva cu. altceva. dar dacă dacă. altfel se va extinde în interior dacă. altfel va duce la o "agățare", ceea ce ar putea face și mai dificilă găsirea unei probleme existente cu o altă problemă, ca în codul următor.
Ideea este să utilizați un punct și virgulă în contexte unde semnul de eroare este greșit. Desigur, în acest moment, puteți (și probabil că ar trebui) să spuneți că ar fi mai bine să declarați BAR ca o funcție reală, mai degrabă decât o macrocomandă.
Așa. în timp ce aveți nevoie pentru a obține în jurul valorii de deficiențele C. În cazul în care stilul de Preprocessor de ghidare C vă spun despre ceea ce ei sunt îngrijorați pentru a elimina preprocesor C, este.
Există trei sfaturi bune pentru a reuși în acest sens:
Ajutați macro-ul să se comporte ca un cod autentic
Un cod normal se termină de obicei cu un punct și virgulă. Dacă utilizatorul are un cod de vizualizare care nu are nevoie de unul.
Aceasta înseamnă că utilizatorul se așteaptă ca compilatorul să genereze o eroare în cazul în care nu există punct și virgulă.
Prin urmare, trebuie să avem o macrocomandă care are nevoie de o semi-colonie.
Creați un cod valid
După cum se arată în răspunsul jfm3, uneori o macrocomandă conține mai multe instrucțiuni. Și dacă macro-ul este utilizat în interiorul instrucțiunii if, va fi problematică:
Această macrocomandă poate fi implementată ca:
Funcția g va fi executată indiferent de valoarea bIsOk.
Aceasta înseamnă că trebuie să adăugăm un scop macro:
Generați codul valid 2
Dacă macrocomanda este ceva asemănător:
S-ar putea să avem o altă problemă în următorul cod:
Întrucât se va extinde după cum urmează:
Desigur, acest cod nu se va compila. Deci, din nou, soluția folosește scopul:
Codul se comportă corect din nou.
O combinație de efecte cu un cursor + scară?
Există un singur idiom C / C ++ care produce acest efect: do / while loop:
face / în timp ce operațiune poate crea un domeniu de aplicare, integrând astfel codul macro și în cele din urmă are nevoie de polutole la sfârșitul anului, crescând astfel de cod este nevoie.
Compilatorul C ++ optimizează circuitul do / while deoarece starea post-stare este falsă, este cunoscută la momentul compilării. Aceasta înseamnă că o macrocomandă cum ar fi:
se va extinde în mod corespunzător, deoarece
și apoi compilate și optimizate ca
@ jfm3 - Aveți un răspuns bun la întrebare. De asemenea, puteți adăuga faptul că idiomul macro previne, de asemenea, comportamentul neintenționat mai periculos (deoarece nu există nicio eroare) cu operațiuni simple "if":
care este corect din punct de vedere sintactic, deci nu există o eroare de compilator, dar probabil că are o consecință neintenționată că g () va fi întotdeauna apelat.
Răspunsurile de mai sus explică sensul acestor construcții, dar nu există nicio diferență semnificativă între ele. De fapt, există motive să preferăm să faceți. în același timp. altfel pentru a construi.
Problema construirii dacă. altfel este că nu te forțează să pui un punct și virgulă. Ca și în acest cod:
Deși am lăsat un punct și virgulă (din greșeală), codul se va extinde la
și se va compila automat (deși unii compilatori pot da un avertisment pentru codul inaccesibil). Dar operatorul printf nu va fi executat niciodată.
do. Deși nu există o astfel de problemă, deoarece singurul token valid după (0) este punct și virgulă.
Deși este de așteptat ca compilatoarele să optimizeze acțiunea în timp ce (false); buclele, există o altă soluție care nu necesită această construcție. Soluția constă în utilizarea operatorului de virgulă:
sau chiar mai exotice:
Deși acest lucru va funcționa bine cu instrucțiuni separate, acesta nu va funcționa cu cazurile în care variabilele sunt create și utilizate ca parte a #define.
Cu aceasta, ați putea folosi construcția do / while.
Biblioteca Preprocesor Jens GUSTEDT (! Da, faptul că un astfel de lucru există, de asemenea, a suflat mintea mea) pentru a îmbunătăți design în cazul în care (1) altfel o mică, dar semnificativă, pentru a determina următoarele:
Motivul pentru aceasta este faptul că, spre deosebire de a face în timp ce (0). pauză și să continue să continue să lucreze într-un anumit bloc, dar ((void) 0) creează o eroare de sintaxă în cazul în virgulă omise după apel macro, care altfel ar fi dor de blocul următor. (De fapt, nu există nici o problemă cu "hanging", deoarece altul este legat la cea mai apropiată dacă. Care este una în macro.)
Dacă sunteți interesat de acele lucruri care se pot face mai mult sau mai puțin în siguranță cu preprocesorul C, consultați această bibliotecă.
Unii dintre voi ați arătat macrocomenzi cu variabile locale, dar nimeni nu a menționat că nu puteți folosi orice nume în macro! El va musca pe utilizator o zi! De ce? Deoarece argumentele de intrare sunt înlocuite în șablonul macro. În exemplele dvs. de macrocomandă, probabil, utilizați cel mai frecvent utilizat nume de variabilă i.
De exemplu, când următoarea macrocomandă
este utilizat în următoarea funcție
macro-ul nu va utiliza variabila asumată i declarată la începutul some_func, dar variabila locală declarată în ciclul do. în timp ce.
Astfel, nu folosiți niciodată numele de variabile comune într-un macro!
va fi tradus în
observați cum i ++ este evaluată de două ori într-o macrocomandă. Acest lucru poate duce la unele erori interesante.
Mai bine decât face <> în timp ce (0) și dacă (1) <> altceva. puteți folosi (<>).
Această sintaxă este compatibilă cu valorile returnate (faceți <> în timp ce (0) nu este), ca în:
Am găsit acest truc foarte util în situațiile în care trebuie să tratezi în mod consecvent o anumită valoare. La fiecare nivel de procesare, în cazul în care există o eroare sau o stare nevalidă, puteți evita procesarea ulterioară și scăparea mai devreme. de exemplu