2 TYPY, OPERATORY I WYRAŻENIA__.______
n = 0;
for (i = 0; s[i] >= ’0’ && s[i] <= ’9’; ++1) n = 10 * n + (s[i] - ’0’); return n;
Jak już wspomnieliśmy w rozdz. 1, wyrażenie s[i] - ’0’
daje numeryczną wartość cyfry zawartej w s[i], gdyż wartości kodów znaków ’0\ T itd. tworzą ciąg rosnących liczb całkowitych.
Innym przykładem przekształcenia typu char na int jest funkcja lower, która zamienia wielkie litery alfabetu na małe i działa poprawnie tylko dla zbioru znaków ASCII. Jeśli znak nie jest wielką literą, to funkcja lower zwraca jego wartość bez zmian.
I* lower: zamień c na małą literę; tylko dla ASCII */ int lower(int c)
if (c >= ’A’ && c <= T)
return c + ’a’ - 'A’; 1
else
return c;
Poprawność działania dla zbioru ASCII wynika z tego, że odległość między kodami odpowiednich wielkich i małych liter jest stała oraz że oba alfabety są ciągłe - między literami A i Z występują jedynie litery. Ta ostatnia właściwość nie obowiązuje jednak w zbiorze znaków EBCDIC, toteż dla tego zbioru nasza funkcja zamieniłaby nie tylko litery. 1
W standardowym pliku nagłówkowym <ctype.h> (opisanym w dodatku B) zdefinio
wano rodzinę funkcji realizujących podobne sprawdzenia i przekształcenia niezależnie od zbioru znaków. Jedną z nich, na przykład, jest funkcja tolower(c), która zwraca wartość małej litery alfabetu określonej przez C, jeśli c jest wielką literą; tolower jest zatem przenośnym zamiennikiem naszej funkcji lower. Podobnie sprawdzenie
c >= ’0’ && c <= *9*
można zastąpić ogólniejszym
isdigit(c) /* czy c jest cyfrą */
Od tej pory będziemy używać funkcji z pliku nagłówkowego <ctype.h>.
27 PRZEKSZTAŁCENIA TYPÓW
Przekształcanie znaków na liczby całkowite ma jeden słaby punkt. Ję; la, czy zmienne typu char są wielkościami ze znakiem liczby czy bez. Gdy typ char jest zamieniany na int, czy kiedykolwiek może powstać liczba ujemna? Odpowiedź zmienia się z maszyny na maszynę, odzwierciedlając różnice w ich architekturze. W niektórych znak, którego skrajnie lewy bit jest równy 1, będzie przekształcony na liczbę ujemną (przez tzw. „powielenie bitu znaku”). W innych typ char awansuje do typu int przez dodanie zer z lewej strony, a więc jest zawsze dodatni.
Definicja języka C gwarantuje, że żaden znak ze standardowego maszynowego zbioru znaków drukowalnych nie będzie ujemny, a więc takie znaki w wyrażeniach będą zawsze wartościami dodatnimi. Lecz dowolne wzorce bitowe zapamiętane w zmiennych znakowych mogą być dla jednych maszyn ujemne, dla innych zaś dodatnie. Ze względu na przenośność oprogramowania, w deklaracjach zmiennych typu char używaj kwalifikatora signed lub unsigned. jeśli masz zamiar przechowywać w nich dane „nieznakowe”.
Z definicji wyrażenia relacyjne typu i > j oraz wyrażenia logiczne połączone operatorami && i 11 będą miały wartość 1 - jeśli są prawdziwe, bądź 0 - jeśli są fałszywe. Zatem w przypisaniu
d = c >= ’0’ && c <= ’9’
zmienna d otrzyma wartość 1, jeśli c jest cyfrą, lub 0, jeśli nie jest. Funkcje biblioteczne, jak np. isdigit, mogą dla oznaczenia stanu „prawda” zwracać dowolne wartości różne od zera. W instrukcjach takich, jak if, while czy for, nie robi to jednak większej różnicy, gdyż „prawda” w ich częściach warunkowych znaczy tyle samo, co „nie zero”.
Niejawne przekształcenia arytmetyczne działają zgodnie z oczekiwaniami. Ogólnie, jeśli argumenty operatora dwuargumentowego (np. + czy 1) są różnego typu, to typ „mniejszy” jest promowany do typu „większego” przed wykonaniem operacji. Typem wyniku jest typ „większy”. Szczegółowe reguły przekształceń typów przedstawiono w dodatku w p.A6. Jeśli jednak nie używasz argumentów unsigned, to na razie wystarczy Ci następujący, nieformalny zestaw reguł:
71
Jeśli którykolwiek z argumentów jest typu long double, to ten drugi zostanie przekształcony do long double.
• W przeciwnym przypadku, jeśli typem któregokolwiek argumentu jest double, to drugi argument będzie przekształcony do double.
• W przeciwnym przypadku, jeśli typem jednego z argumentów jest float, to drugi argument będzie przekształcony do float.
• W przeciwnym przypadku, wszystkie obiekty typu char i short są przekształcane do int.