Kilka uwag… (część 2)

Oglądając kawałek kodu starajcie się zastanawiać precyzyjnie co oznacza każdy jego fragment.

  1. Widzimy 2 Jest to stała typu int. 2. (dwójka z kropką) to stała typu double. (Jak w tym kontekście wygląda stała typu float?). Co to jest 'a' ? Jest to stała typu char. Natomiast "a" to stała typu char * („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 kodzie 0 ( '\0' ).

  2. Widzimy gwiazdkę (*) patrzymy w jakim kontekście ona występuje. Czy jest to kontekst typu a * b (albo 2 * 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ład double * 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.

  3. Przypominam, że identycznie rozróżnia się jednoargumentowy znak - (zmiana znaku, na przykład: -3) od dwuargumentowego operatora - (odejmowanie, na przykład a - b).

  4. 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żne int) 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ż zapis float a = 'a';. Zostanie dokonana tu konwersja z char do int a następnie do float.

  5. 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 czy else if musi być para nawiasów. Jak jest tam tylko jedno polecenie — nie musi.

  6. 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.

  7. 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.

  8. 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 (){}

Wojciech Myszka
Wojciech Myszka
dr inż. adiunkt

Tak się tylko rozglądam…