167
KONWENCJE PISANIA MAKIi
Ponieważ makra preprocesora działają na zasadzie zwykłego zastępowania napisów, są |xxłatne na wiele kłopotliwych błędów, z których części można uniknąć przez stosowanie się do poniższych reguł:
1. Umieszczaj nawiasy dookoła argumentów makra kiedy to tylko możliwe. Za|>ewnia to, że gdy są wyrażeniami kolejność działań nie zostanie zmieniona. Na przykład:
• Źle: Sdefine kwadrat(z) (x*x)
• Dobrze: sdefine kwadrat(x) ( (x)*(x) )
• Przykład: Załóżmy, że w programie makro kwadrat() zdefiniowane bez nawiasów zostało wywołane następująco: kwadrat(a*b). Wtedy zostanie ono zamienione przez preprocesor na: a*b*a+b. Z kolejności działań wiemy, że najpierw zostanie wykonane mnożenie, więc wartość wyrażenia kwadrat (a+b) będzie różna od kwadratu wyrażenia a+b.
2. Umieszczaj nawiasy dookoła całego makra, jeśli jest pojedynczym wyrażeniem. Ponownie, chroni to przed zaburzeniem kolejności działań.
• Źle: sdofino kwadrat(x) (x)*(x)
• Dobrze: sdofine kwadrat(x) ( (x)*(x) )
• Przykład: Definiujemy makro Sdefine sura (a, b) (a)+(b) i wywołujemy je w kodzie wynik = suma(3, 4) * 5. Makro zostanie rozwinięte jako wynik = 3+4*5. co z powodu kolejności działań da wynik inny niż pożądany.
3- Jeśli makro składa się z wielu instrukcji lub deklaruje zmienne, powinno być umieszczone w pętli do { } while(O), bez kończącego średnika. Pozwala to na użycie makra
jak pojedynczej instrukcji w każdym miejscu, jak ciało innego wyrażenia, |x>zwałając jednocześnie na umieszczenie średnika po makrze bez tworzenia zerowego wyrażenia. Należy uważać, by zmienne w makrze (totencjalnie nie kolidowały z argumentami makra.
• Źle: sdefine FREE(p) free(p); p - NULL;
• Dobrze: Sdefine FREE(p) do { free(p); p ■ NULL; } while(O)
4. Unikaj używania argumentów makra więcej niż raz wewnątrz makra. Maże to spowodować kłopoty, gdy argument makra ma efekty ul>oezne (np. zawiera operator inkre-mentacji).
• Przykład: Sdefine kwadrat(x) ((x)*(x)) nie powinno bvć wywoływane z operatorem inkrementarji kwadrat (a++) ponieważ zostanie to rozwinięte jako ((a++) • (&**)), co jest niezgodne ze spee>'fikacją języka i zachowanie takiego wyrażenia jest niezdefiniowane (dwukrotna inkrementacja w tym samym wyrażeniu).
5. Jeśli makro może być w przyszłości zastąpione przez funkcję, rozważ użycie w nazwie małych liter, jak w funkcji.
Wiemy, że komputer to maszyna, której najmniejszą jednostką pamięci jest bit. jednak w C najmniejsza zmienna ma rozmiar 8 bitów (czyli jednego bajtu). Jak zatem można odczytać wartość pojedynczych bitów? W bardzo prosty sposób w zestawie operatorów języka C znajdują się tzw. operatory bitowe. Są to m. in.:
• & logiczne “i”
• — logiczne “lub”