proszę o ocenę tutoriala - funkcje w języku C

Odpowiedz Nowy wątek
2019-09-12 17:15

Rejestracja: 5 miesięcy temu

Ostatnio: 5 miesięcy temu

0

cześć, piszę mały tutorial na temat funkcji w C dla znajomych z polibudy. czy powinienem zamieścić jeszcze coś, żeby pomóc im zrozumieć funkcje?

Podstawy programowania

Programowanie to pisanie instrukcji dla procesorów. Procesory wykonują instrukcje linijka po linijce, z góry do dołu.

Wyrażenia

Wyrażenia w językach programowania to wszystko co zwraca wartość. Mogą to być wyrażenia matematyczne, lub wywołania funkcji. Funkcje, które zwracają void też są wyrażeniami, ale używanie wartości wyrażenia ich wywołania jest błędem i uniemożliwi kompilacje programu w językach C i pochodnych.

Funkcje (podejście matematyczne)

Żeby zrozumieć funkcje trzeba podejść do nich z dwóch stron: należy zrozumieć matematyczne pojęcie funkcji oraz sposób, w jaki wykonywane są przez procesor komputera.

Ze strony matematycznej funkcja to przyporządkowanie pewnym argumentom wartości. Wywołując funkcję z pewnymi argumentami otrzymamy pewną wartość. W matematyce wywoływanie funkcji z danymi argumentami dowolną ilość razy zawsze da ten sam wynik. Funkcje, którę będziemy pisać nie są matematyczne i nie obowiązuje ich ta zasada. Funkcje, które mimo tego trzymają się tej reguły nazywamy czystymi.

Wyrażenie wywołania czystej funkcji jest równe wynikowi tej funkcji, czyli wyrażenie 2 + 2; jest równe wyrażeniu dodaj(2, 2); i jest równe wyrażeniu 4;. Przy definicji funkcji dodaj:

int dodaj(int a, int b) { return a + b; }
// funkcja czysta bo do ustalenia wyniku korzysta tylko z argumentów

Czyste funkcje pozwalają nie myśleć o sobie jak o podprogramie, który wykonuje polecenia, które trzeba znać bo mogą mieć konsekwencje w dalszym działaniu programu. Dzięki temu, że funkcja ta nie może mieć wpływu na stan programu można myśleć o jej wywołaniu jak o statycznym wyrażeniu. W matematyce, mówiąc o sinusie z 30 stopni nie myślimy o procedurze, jaką należałoby przeprowadzić, tylko o wyniku - liczbie 0,5. Dlatego, mówiąc o wyrażeniu dodaj(2, 2) nie należy myśleć o procedurze dodawania wykonywanej podczas wywołania funkcji, lecz o jej wyniku jak o wartości stałej - liczbie 4. Matematyczne wywołanie funkcji to jak przeczytanie wyniku dla odpowiednich argumentów z wydrukowanej tabeli. Wynik będzie zawsze taki sam dla takich samych argumentów i przeczytanie go z tabeli nie będzie miało żadnych skutków ubocznych jak zmiana jakiejś innej wartości w tabeli.

Stos

Zrozumienie funkcji od strony sprzętowej wymaga rozumienia pojęcia stosu. Stos jako struktura danych pozwala na dodawanie danych i zdejmowanie ich. Ważna jest kolejność zdejmowania. Zdjąć ze stosu można tylko dane umieszczone na nim najpóźniej (znajdujące się na jego szczycie). Żeby usunąć podstawę stosu trzeba po kolei zdejmować wszystkie wartości umieszczone na stosie po umieszczeniu podstawy.

Sprzętowo, stos to pewna ilość zaalokowanej pamięci RAM. Każdy proces uruchomiony w komputerze dostaje swój stos. W procesorze komputera znajduje się rejestr przechowywujący liczbę całkowitą - adres bitu pamięci ram, który jest w danym momencie szczytem stosu; nazywa się go wskaźnikiem stosu.

Wywołanie funkcji (sprzętowo)

Sprzętowa implementacja funkcji jest mniej abstrakcyjna i można podzielić ją na kilka etapów

  1. Przesunięcie wskaźnika stosu, tak aby zmieściły sie pod nim wartości wszystkich argumentów funkcji i jej zmiennych lokalnych

  2. Wykonanie operacji z definicji funkcji

  3. Opcjonalne przepisanie wyrażenia po słowie kluczowym return w odpowiednie miejsce w pamięci

  4. Przesunięcie wskaźnika stosu w miejsce, w którym był przed wykonaniem kroku 1.

Zasięg zmiennych

W językach programowania zasięg zmiennych to części kodu, w których można korzystać z określonych zmiennych. Zmienne globalne mają zasięg w każdym miejscu programu. Zmienne lokalne są w zasięgu tylko w bloku kodu, w którym zostały zdefiniowane. W języku C++ bloki kodu są określone klamrami. Przy rozpoczęciu bloku kodu na stos zostaje włożony nowy segment, który będzie przechowywał zmienne w tym bloku. Po wyjściu programu z bloku kodu, wskaźnik stosu zostaje cofnięty co powoduje usunięcie wszystkich zmiennych w opuszczonym bloku.

Zmienne zdefiniowane w bloku kodu znajdującym się w innym bloku mają dostęp do zmiennych ze wszystkich nadrzędnych bloków.

int a;
void func() {
    int b;
    {
        int c;
        {
            int d;
            cout << a + b + c + d << endl; // Prawidłowe wyrażenie
        } // <- tu zmienna d zostaje skasowana
    } // <- tu zmienna c zostaje skasowana
} // <- tu zmienna b zostaje skasowana

Pozostało 580 znaków

2019-09-12 17:39

Rejestracja: 12 lat temu

Ostatnio: 1 godzina temu

1

W tytule i opisie widzę C w kodzie widzę C++!
Może warto by było, żebyś obejrzał to.

gbjk napisał(a):

Wywołanie funkcji (sprzętowo)

Sprzętowa implementacja funkcji

WAT? Chyba wiem o co ci chodziło, ale ująłeś to w takie słowa, że zajęło mi to chwilę.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 4x, ostatnio: MarekR22, 2019-09-12 17:45

Pozostało 580 znaków

2019-09-12 18:03

Rejestracja: 2 lata temu

Ostatnio: 15 minut temu

0

Jak dla mnie to jest dośc niezrozumiałe:

  1. Przesunięcie wskaźnika stosu, tak aby zmieściły sie pod nim wartości wszystkich argumentów funkcji i jej zmiennych lokalnych

Nie trzeba przesuwać wskaźnika stosu, żeby zaalokować zmienne lokalne, bo kompilator zwykle używa do tego rejestru ebp/rbp bez przesunięcia esp/rsp. Generalnie można powiedzieć kompilatorowi, żeby używał esp/rsp poprzez flagę -fomit-frame-pointer, ale by default tego nie ma.
Co więcej do przekazywania argumentów funkcjom również nie zawsze używa się do tego stosu i jego wskaźnika. Przy architekturze x86 owszem, ale w x64 najczęściej stosowana konwencja wywołań oparta jest o rejestry -> https://stackoverflow.com/que[...]ystem-calls-on-i386-and-x86-6


Pozostało 580 znaków

2019-09-12 18:11

Rejestracja: 7 lat temu

Ostatnio: 2 godziny temu

0
gbjk napisał(a):

cześć, piszę mały tutorial na temat funkcji w C dla znajomych z polibudy. czy powinienem zamieścić jeszcze coś, żeby pomóc im zrozumieć funkcje?

Lepiej powiedz im, żeby poczytali K&R, bo do zrozumienia funkcji nie potrzeba schodzić głęboko, a mieszanie początkującym w głowie nie sprzyja nauce.

edytowany 1x, ostatnio: Saalin, 2019-09-12 18:11

Pozostało 580 znaków

2019-09-12 18:12

Rejestracja: 5 miesięcy temu

Ostatnio: 5 miesięcy temu

0
Shizzer napisał(a):

Jak dla mnie to jest dośc niezrozumiałe:

  1. Przesunięcie wskaźnika stosu, tak aby zmieściły sie pod nim wartości wszystkich argumentów funkcji i jej zmiennych lokalnych

Nie trzeba przesuwać wskaźnika stosu, żeby zaalokować zmienne lokalne, bo kompilator zwykle używa do tego rejestru ebp/rbp bez przesunięcia esp/rsp. Generalnie można powiedzieć kompilatorowi, żeby używał esp/rsp poprzez flagę -fomit-frame-pointer, ale by default tego nie ma.
Co więcej do przekazywania argumentów funkcjom również nie zawsze używa się do tego stosu i jego wskaźnika. Przy architekturze x86 owszem, ale w x64 najczęściej stosowana konwencja wywołań oparta jest o rejestry -> https://stackoverflow.com/que[...]ystem-calls-on-i386-and-x86-6

Dzięki za to bo nie wiedziałem, ale moim celem jest wytłumaczenie działania funkcji w językach C/C++ i wydaje mi się że wytłumaczenie ze wskaźnikiem stosu to dość pożyteczne uogólnienie. Z architektury systemów komputerowych mieliśmy tylko x86 więc nie chcę wprowadzać innych procesorów.

Pozostało 580 znaków

2019-09-12 18:16

Rejestracja: 2 lata temu

Ostatnio: 15 minut temu

0

Fajnie, że próbujesz to wytłumaczyć też nisko poziomowo, ale:

  1. Dla początkujących jest to zbędne, bo tylko zaśmiecają sobie tym głowę na początku. Dla średnio-zaawansowanych to już może przejść.
  2. Architektura x86 powoli usuwa się w cień, a x64 przejmuje kontrolę także jeśli już piszesz o tym w tutorialu to bardziej kieruj uczniów w stronę x64. ;)

Przy czym jak spojrzymy odpowiednio nisko to wstep: Procesory wykonują instrukcje linijka po linijce, z góry do dołu. nie jest prawda. Ale jak patrzymy z poziomu high-lev to mozna tak myslec. Wiec po co poczatkujacego low-lev meczyc :p - stivens 2019-09-12 18:18
Dokładnie. Takie rzeczy są ciekawe, ale dla początkujących nieistotne - Shizzer 2019-09-12 18:22

Pozostało 580 znaków

2019-09-12 18:19

Rejestracja: 5 miesięcy temu

Ostatnio: 5 miesięcy temu

0
Shizzer napisał(a):
  1. Dla początkujących jest to zbędne, bo tylko zaśmiecają sobie tym głowę na początku. Dla średnio-zaawansowanych to już może przejść.

Napisałem to bo zauważyłem, że mają problem ze zrozumieniem, dlaczego nie mogą zwrócić wskaźnika do zmiennej lokalnej. To wytłumaczenie stosu przydaje się też do zrozumienia rekurencji. Samo wytłumaczenie matematyczne nie wystarczyłoby do zrozumienia np. przepełnienia stosu czy optymalizacji rekurencji ogonowej

Pozostało 580 znaków

2019-09-12 18:22

Rejestracja: 3 lata temu

Ostatnio: 15 godzin temu

0

Dobrze rozumiem, ze mieliscie zajecia z architektur ale koledzy nie rozumieja funkcji? Tzn. myslalem ze to jakis nieinformatyczny kierunek i stad trzeba takie rzeczy tlumaczyc a tu zonk


01010100 01110101 01110100 01100001 01101010 00100000 01101110 01101001 01100101 00100000 01101101 01100001 00100000 01101110 01101001 01100011 00100000 01100011 01101001 01100101 01101011 01100001 01110111 01100101 01100111 01101111 00101110 00100000 01001001 01100011 00100000 01110011 01110100 01101111 01101110 01110100 00101110

Pozostało 580 znaków

2019-09-12 18:33

Rejestracja: 2 lata temu

Ostatnio: 15 minut temu

0

Napisałem to bo zauważyłem, że mają problem ze zrozumieniem, dlaczego nie mogą zwrócić wskaźnika do zmiennej lokalnej. To wytłumaczenie stosu przydaje się też do zrozumienia rekurencji. Samo wytłumaczenie matematyczne nie wystarczyłoby do zrozumienia np. przepełnienia stosu czy optymalizacji rekurencji ogonowej

W takim razie jest to zrozumiałe jeśli chcieli wiedzieć dlaczego tak się dzieje. Ale wtedy powinieneś raczej wkleić jakieś screeny debuggera, żeby przekonali się jak sprawa wygląda w pamięci. Taka sucha teoria może być dość trudna do zrozumienia.


Pozostało 580 znaków

2019-09-12 20:16

Rejestracja: 3 lata temu

Ostatnio: 52 minuty temu

0

Jak widać nie jest prosto coś, napisać. A można też sięgnąć po gotowe rzeczy, ja bym im dał np., to:
http://cslibrary.stanford.edu/101/EssentialC.pdf


Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0