Kilka uwag… (część 2)
Oglądając kawałek kodu starajcie się zastanawiać precyzyjnie co oznacza każdy jego fragment.
Widzimy
2
Jest to stała typuint
.2.
(dwójka z kropką) to stała typu double. (Jak w tym kontekście wygląda stała typufloat
?). Co to jest'a'
? Jest to stała typuchar
. Natomiast"a"
to stała typuchar *
(„char gwiazdka”, czyli wskaźnik do tego miejsca w pamięci, w którym zapisany jest napis o długości dwu znaków składający się ze znaku'a'
i znaku o kodzie0
('\0'
).Widzimy gwiazdkę (*) patrzymy w jakim kontekście ona występuje. Czy jest to kontekst typu
a * b
(albo2 * b
)? Jeżeli tak, gwiazdka ma charakter dwuargumentowego operatora mnożenia. gdy występuje na lewo od zmiennej (* a
) wówczas jeżeli zmienna zadeklarowana jest jako wskaźnik (na przykładdouble * a;
) to*a
oznacza dostęp do zawartości pamięci wskazywanej przez wskaźnik. Gdy po lewej stronie znaku nie ma nic, a po prawej stronie jest stała albo zmienna — będzie błąd.Przypominam, że identycznie rozróżnia się jednoargumentowy znak
-
(zmiana znaku, na przykład:-3
) od dwuargumentowego operatora-
(odejmowanie, na przykłada - b
).O stałych (i zmiennych) typu znakowego pamiętamy, że mogą być traktowane jako stałe (i zmienne) typu całkowitego. W związku z tym wszystkie operacje arytmetyczne są dozwolone. Zatem
'a'/200
interpretujemy tak: Iloraz. Dzielna to stała znakowa (o nieznanej z pamięci wartości całkowitej mieszczącej się pomiędzy 0 a 127). Dzielnik - stała całkowita o wartości 200. Ponieważ po obu stronach znaku dzielenia są stałe zbliżonego typu (char
jest równoważneint
) dzielenie ma charakter całkowity: coś mniejsze od 200 dzielone przez dwieście, daje w wyniku 0. W żadnym wypadku nie jest to_dzielenie litery a n 200 części czy kawałków_. Poprawny jest również zapisfloat a = 'a';
. Zostanie dokonana tu konwersja zchar
doint
a następnie dofloat
.Oglądając kawałek kodu nie patrzcie na wcięcia: przecież prawie nigdy ich nie stosujecie! Patrzcie na nawiasy klamrowe i czy są sparowane. Nie jest prawdą, że po każdej instrukcji
if
,else
czyelse if
musi być para nawiasów. Jak jest tam tylko jedno polecenie — nie musi.Dynamiczny przydział pamięci to przydział pamięci realizowany za pomocą funkcji
malloc
(calloc
) i odbywa się on w trakcie uruchamiania programu, nie w czasie kompilacji, czy ładowani programu do pamięci.Wielokrotnie wspominałem o funkcji „swap” i o konieczności realizowania jej za pomocą wskaźników — w przeciwnym razie efekt zamiany nie powoduje żadnych skutków. Jedno z zadań (F) to były różne warianty tego problemu. Nie uważam (w odróżnieniu od niektórych) że przykład ten był niejasny i pogmatwany. Właściwe użycie wskaźników bądź ich brak wpływają na wynik.
Poniżej jak najbardziej poprawna definicja funkcji:
f(x) { return x * x; }
zwracam uwagę, e nie został tu określony typ argumentu ani typ funkcji. Zgodnie z konwencją języka C w tym przypadku zapis taki jest równoważny
int f(int x)
. W szczególności można zatem napisaćmain (){}