DODATEK A PRZEWODNIK JĘZYKA C_________
Obiekt typu całkowitego można jawnie przekształcić na wskaźnik. Przekształcenie to zawsze zachowa wartość wskaźnika, jeżeli tylko otrzymano go z przekształcenia dostatecznie obszernej wartości całkowitej, która przedtem powstała z przekształcenia tego wskaźnika; w pozostałych przypadkach zależy od implementacji.
Wskaźnik jednego typu może być przekształcony na wskaźnik innego typu. Wynikowy wskaźnik może powodować błąd adresowania, jeśli odnosi się do obiektu źle położonego w pamięci. Gwarantuje się, że przekształcenie wskaźnika pewnego typu na wskaźnik innego typu o mniejszych lub równych ograniczeniach dotyczących położenia w pamięci (i z powrotem) zachowa wartość wskaźnika wyjściowego. Znaczenie pojęcia „ograniczenie dotyczące położenia w pamięci” (ang. alignment) zależy od implementacji, ale obiekty typu char są najmniej ograniczone. Jak to będzie opisane w p. A6.8, dowolny wskaźnik można przekształcić do typu void * i z powrotem bez zmiany.
Wskaźnik może być przekształcony na inny wskaźnik o takim samym typie, ale z innym zestawem kwalifikatorów typu obiektów (p. A4.4, A8.2) wskazywanych przez ten wskaźnik. Jeśli dochodzą nowe kwalifikatory, to nowy wskaźnik jest równoważny ze starym, przy czym obowiązują dodatkowe ograniczenia wynikające z nowych kwalifikatorów. Jeśli kwalifikatorów ubywa, to operacje na wskazywanych obiektach nadal podlegają ograniczeniom wynikającym z kwalifikatorów podanych w oryginalnej deklaracji*
Na koniec, wskaźniki do funkcji można przekształcić na wskaźniki do funkcji innego typu. Wywołanie funkcji za pomocą przekształconego wskaźnika zależy od implementacji, natomiast wynik przekształcenia tego wskaźnika z powrotem do jego oryginalnego typu jest identyczny z oryginalnym wskaźnikiem.
Wartości (nie istniejącej) obiektu typu void nie można wykorzystać w żaden sposób ani nie można przekształcić, jawnie czy niejawnie, do innego typu różnego od void. Ponieważ wyrażenie typu void oznacza nie istniejącą wartość, takich wyrażeń można użyć jedynie w miejscach, gdzie wartość nie jest wymagana, na przykład jako instrukcję wyrażeniową (p. A9.2) lub jako lewy argument operatora przecinkowego (p. A7.18).
Typ void nie występował w pierwszym wydaniu książki, lecz od dawna jest w powszechnym użyciu.
Każdy wskaźnik do obiektu może być przekształcony do typu void * bez utraty informacji. Przekształcenie wyniku z powrotem do wskaźnika oryginalnego typu przywraca oryginalny wskaźnik. W przeciwieństwie do tych przekształceń wskaźników do
A7 WYRAŻENIA
powered by
wskaźników, omówionych w p. A6.6, które wymagały jawnego rzutowi............—.....
do obiektu można wstawić do (lub otrzymać wartość od) wskaźnika typu void *, a także porównywać z takim wskaźnikiem.
Ta interpretacja wskaźników typu void * jest nowa; poprzednio rolę wskaźników ogólnych spełniały wskaźniki typu char *. W przypisaniach i porównaniach ANSI C wyraźnie „błogosławi” kojarzenie wskaźników do obiektów ze wskaźnikami typu void *, wymagając zarazem jawnego rzutowania w przypadku innych kombinacji wskaźników.
Porządek priorytetów operatorów w wyrażeniach jest taki sam, jak porządek głównych podpunktów niniejszego punktu, poczynając od priorytetu najwyższego. Na przykład wyrażenia, o których mówi się jako o argumentach operatora + (p. A7.7), są wyrażeniami zdefiniowanymi w p. A7.1-A7.6. Opisane w poszczególnych podpunktach operatory mają równy priorytet. Tam określono również lewostronną lub prawostronną łączność' tych operatorów. Priorytety i łączność wszystkich operatorów są zestawione w gramatyce języka (p. Al3).
Priorytety i łączność operatorów są w pełni określone; nie jest natomiast określona (poza kilkoma wyjątkami) kolejność obliczania wyrażeń, nawet jeśli podwyrażenia powodują efekty uboczne. Oznacza to, że jeśli definicja operatora nie gwarantuje obliczenia argumentów w szczególnej kolejności, to w implementacjach zezwala się na swobodę w kolejności obliczania argumentów, a nawet na mieszanie tych obliczeń. Każdy operator gromadzi jednak swoje argumenty zgodnie z rozbiorem składniowym wyrażenia, w którym występuje.
Ta reguła anuluje dotychczasową swobodę w reorganizacji wyrażeń z operatorami, które są matematycznie przemienne i łączne, ale mogą nie być łączne obliczeniowo. Zmiana dotyczy tylko rachunku zmiennopozycyjnego na granicy dokładności i sytuacji, gdy jest możliwy nadmiar.
Sposób postępowania przy nadmiarze, błędach dzielenia i innych sytuacjach wyjątkowych podczas obliczania wyrażeń nie jest zdefiniowany w języku. Większość istniejących implementacji C ignoruje nadmiar przy obliczaniu wyrażeń i w przypisaniach dla wielkości całkowitych ze znakiem, ale to zachowanie się nic jest gwarantowane.
Por. przypis na str. 82.
263