53
KOLEJNOŚĆ WYLICZANIA ARGUMENTÓW OPERATORA
jednak z tyin przesadzać, gdyż kod programu może stać się mylący nie tylko dla innych, ale po latach (czy nawet i dniach) również dla nas.
Warto także podkreślić, że operator koniunkcji ma niższy priorytet niż operator porównania1. Oznacza to, że kod
if (flags k FL.MASK — FL.FOO)
zazwyczaj da rezultat inny od oczekiwanego. Najpierw’ Imwicm wykona się porównanie wartości FL.MASK z wartością FL.FOO, a dopiero |K>tem koniunkcja bitowa. W takich sytuacjach należy pamiętać o użyciu nawiasów:
if ((flags t FL.MASK) == FL.FOO)
Kompilator GCC potrafi wykrywać takie błędy i aby to robił należy podać mu argument -Wparentheses.
W przypadku większości operatorów (wyjątkami są tu ||i przecinek) nie (La się określić, która wartość argumentu zostanie obliczona najpierw. W większości przypadków nie ma to większego znaczenia, lecz w przypadku wyrażeń, które mają efekty uboczne wymuszenie konkretnej kolejności może być potrzebne. Weźmy dla przykładu program
#include <stdio.h>
int foo(int a) { printf("'/«d\n", a); return 0;
int main(void) { return foo(l) + foo(2);
Otóż. nie wiemy czy najpierw zostanie wywołana funkcja foo z parametrem jeden, czy dwa. Jeżeli ma to znaczenie należy użyć zmiennych pomocniczych zmieniając definicję funkcji main na:
int main(void) { int tmp ■ foo(l); return tmp + foo(2);
Teraz już na pewno najpierw zostanie wypisana jedynka, a potem dopiero dwójka. Sytuacja jeszcze bardziej się komplikuje, gdy używamy wyrażeń z efektami ubocznymi jako argumentów funkcji, np.:
Jwt to uuakwć historyczna z czasów, gdy nic liyło logicznych o|>cratorów AcAc oraz ||i zamiast nich stosowano operatory bitowe & oraz |.