2 TYPY, OPERATORY I WYRAŻENIA______________
„weź i, dodaj 2, a następnie umieść wynik z powrotem w i”. Dlatego właśnie wyrażenie i += 2 jest lepsze niż i = i + 2. Co więcej, w skomplikowanych wyrażeniach, jak np.
yyval[yypv[p3+p4] + yyPvtP1+P2]] += 2
taki operator przypisania ułatwia zrozumienie programu, Czytelnik nie musi bowiem starannie sprawdzać, czy dwa długie wyrażenia są rzeczywiście identyczne, lub zastanawiać się, dlaczego nie są. Operator przypisania może nawet pomóc kompilatorowi przy generowaniu bardziej efektywnego kodu.
Widzieliśmy już, że przypisanie ma wartość i może pojawić się w wyrażeniach; najczęściej spotykanym przykładem jest
while ((c = getchar()) != EOF)
• • •
W wyrażeniach mogą pojawić się także inne operatory przypisania (jak +=, -= itd.), jednak częstość ich występowania jest mniejsza.
We wszystkich takich wyrażeniach typem wyrażenia przypisania jest typ jego lewego argumentu, a jego wartością staje się przypisana wartość.
Ćwiczenie 2.9. W arytmetyce uzupełnieniowej do 2 wyrażenie x &= (x-1) usuwa jedynkę ze skrajnie prawego bitu zmiennej x. Wyjaśnij, dlaczego. Zastosuj tę obserwację do napisania szybszej wersji funkcji bitcount.
Instrukcja
if (a > b) z = a; else z = b;
powoduje wstawienie do z większej z liczb a i b. Wyrażenie warunkowe utworzon-za pomocą trzyargumentowego operatora pozwala zapisać tę i podobne konstrukcje w inny sposób. W wyrażeniu
wyrl ? wyrl : wyr3 i
najpierw oblicza się wyrażenie wyrl. Jeśli jego wartość jest różna od zera („prawd? wa”), to oblicza się wyrażenie wyrl i ta wartość będzie wartością całego wyra# nia warunkowego. W przeciwnym przypadku oblicza się wyrażenie wyr3 i jego W*
I powered by
2-12 PRIORYTETY I KOLEJNOŚĆ OBLICZEŃ ____I-B---a-
tość stanie się wartością wyniku. Spośród wyrażeń \vyr2 oraz wyinu jedno. Aby wyznaczyć z jako większą z liczb a i b, wystarczy więc napisać
z = (a > b) ? a : b; /* z = max(a,b) */
Zwróć uwagę na to, że wyrażenie warunkowe jest prawdziwym wyrażeniem i może być stosowane wszędzie tam, gdzie mogą wystąpić inne wyrażenia. Jeśli wyr2 i wyr3 mają różne typy, to typ wyniku będzie określony zgodnie z regułami przekształceń, opisanymi wcześniej w tym rozdziale. Na przykład, jeśli f jest typu float, a n jest typu int, to typem wartości wyrażenia
(n > 0) ? f: n
będzie float niezależnie od tego, czy wartość n jest dodatnia czy nie.
W wyrażeniu warunkowym nawiasy otaczające pierwsze wyrażenie nie są konieczne, priorytet operatora ?: jest bowiem bardzo niski - tuż nad priorytetem przypisań. Warto jednak stosować nawiasy dla uwypuklenia części warunkowej wyrażenia.
Wyrażenie warunkowe często wpływa na zwięzłość programu. Na przykład poniższa pętla wypisuje n elementów tablicy a, po 10 w każdym wierszu, oddzielając każdą kolumnę odstępem oraz kończąc każdy wiersz (wraz z ostatnim) znakiem nowego wiersza.
for (i = 0; i < n; i++)
printf(”%6d%c’\ a[i], (i%10 == 9 || i == n-1) ? ’\n’: ’ ’);
Znak nowego wiersza jest wypisywany po każdym dziesiątym elemencie tablicy oraz po elemencie n-tym. Po wszystkich innych elementach jest wypisywany jeden znak odstępu. Może wygląda to jak sztuczka, ale jest bardziej zwarte niż równoważna konstrukcja zbudowana z if-else. Innym dobrym przykładem jest instrukcja
printf(”Masz %d częś%s.\n’\ n, n == 1 ? "ć” : ”ci”);
Ćwiczenie 2.10. W nowej wersji funkcji lower, zamieniającej wielkie litery alfabetu na małe, zamiast konstrukcji if-else zastosuj wyrażenie warunkowe.
Tablica 2-1 zawiera podsumowanie dotyczące priorytetów i łączności' wszystkich operatorów, także tych, o których dotychczas nie wspominaliśmy. Operatory wymienione w jednym wierszu mają ten sam priorytet. Wiersze są uporządkowane według priorytetu malejącego, a więc np. operatory *, / i % mają ten sam priorytet i jest on wyższy niż priorytet dwuargumentowych operatorów + i -. „Operator” () dotyczy wywołania funkcji. Operatory —> oraz . są używane przy dostępie do elementów
<> - Język ANSI C 81