Wskaźniki w C. Anna Gogolińska

Podobne dokumenty
Wskaźniki. Przemysław Gawroński D-10, p marca Wykład 2. (Wykład 2) Wskaźniki 8 marca / 17

Tablice, funkcje - wprowadzenie

Lab 9 Podstawy Programowania

Podstawy programowania komputerów

Co to jest sterta? Sterta (ang. heap) to obszar pamięci udostępniany przez system operacyjny wszystkim działającym programom (procesom).

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Wskaźniki. Informatyka

Tablice, funkcje, wskaźniki - wprowadzenie

Wskaźnik może wskazywać na jakąś zmienną, strukturę, tablicę a nawet funkcję. Oto podstawowe operatory niezbędne do operowania wskaźnikami:

DYNAMICZNE PRZYDZIELANIE PAMIECI

Programowanie komputerowe. Zajęcia 4

KURS C/C++ WYKŁAD 6. Wskaźniki

Wstęp do wskaźników w języku ANSI C

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Struktury czyli rekordy w C/C++

Tablice (jedno i wielowymiarowe), łańcuchy znaków

> C++ wskaźniki. Dane: Iwona Polak. Uniwersytet Śląski Instytut Informatyki 26 kwietnia 2017

ZASADY PROGRAMOWANIA KOMPUTERÓW

Wskaźniki i dynamiczna alokacja pamięci. Spotkanie 4. Wskaźniki. Dynamiczna alokacja pamięci. Przykłady

Podstawy informatyki. Informatyka stosowana - studia niestacjonarne. Grzegorz Smyk. Wydział Inżynierii Metali i Informatyki Przemysłowej

Materiał Typy zmiennych Instrukcje warunkowe Pętle Tablice statyczne Wskaźniki Tablice dynamiczne Referencje Funkcje

wykład II uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - funkcje, tablice i wskaźniki wykład II dr Jarosław Mederski Spis

Functionalization. Funkcje w C. Marcin Makowski. 30 listopada Zak lad Chemii Teoretycznej UJ

Globalne / Lokalne. Wykład 15. Podstawy programowania (język C) Zmienne globalne / lokalne (1) Zmienne globalne / lokalne (2)

Podstawy programowania w języku C++

Wskaźniki. nie są konieczne, ale dają językowi siłę i elastyczność są języki w których nie używa się wskaźników typ wskaźnikowy typ pochodny:

Stałe, tablice dynamiczne i wielowymiarowe

Programowanie w języku C++

Podstawy programowania. Wykład 6 Wskaźniki. Krzysztof Banaś Podstawy programowania 1

Funkcja (podprogram) void

Informatyka I: Instrukcja 4.2

int tab[5]; tab[1]; ciągły obszar pamięci, w którym umieszczone są elementy tego samego typu macierz [ ] - dwuargumentowy operator indeksowania

Języki i metodyka programowania. Wskaźniki i tablice.

Zmienne, stałe i operatory

Wskaźniki. Programowanie Proceduralne 1

Wstęp do programowania INP001213Wcl rok akademicki 2018/19 semestr zimowy. Wykład 4. Karol Tarnowski A-1 p.

Podstawy programowania w języku C++

część 8 wskaźniki - podstawy Jarosław Gramacki Instytut Informatyki i Elektroniki Podstawowe pojęcia

Podstawy programowania. Wykład 6 Złożone typy danych: struktury, unie. Krzysztof Banaś Podstawy programowania 1

Wstęp do Programowania, laboratorium 02

Język C zajęcia nr 11. Funkcje

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 16 kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 27

1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami

IX. Wskaźniki.(3 godz.)

Wstęp do programowania INP003203L rok akademicki 2018/19 semestr zimowy. Laboratorium 2. Karol Tarnowski A-1 p.

Programowanie I C / C++ laboratorium 03 arytmetyka, operatory

wykład III uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - zarządzanie pamięcią, struktury,

Wykład 1: Wskaźniki i zmienne dynamiczne

// Liczy srednie w wierszach i kolumnach tablicy "dwuwymiarowej" // Elementy tablicy są generowane losowo #include <stdio.h> #include <stdlib.

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.

Konwersje napis <-> liczba Struktury, unie Scanf / printf Wskaźniki

Programowanie w C++ Wykład 5. Katarzyna Grzelak. 26 marca kwietnia K.Grzelak (Wykład 1) Programowanie w C++ 1 / 40

TABLICE W JĘZYKU C/C++ typ_elementu nazwa_tablicy [wymiar_1][wymiar_2]... [wymiar_n] ;

Język ANSI C tablice wielowymiarowe

Podstawy programowania. Wykład Pętle. Tablice. Krzysztof Banaś Podstawy programowania 1

2 Przygotował: mgr inż. Maciej Lasota

Spis treści WSKAŹNIKI. DYNAMICZNY PRZYDZIAŁ PAMIĘCI W JĘZYKU C. Informatyka 2. Instrukcja do pracowni specjalistycznej z przedmiotu

Instrukcja do ćwiczeń nr 4 typy i rodzaje zmiennych w języku C dla AVR, oraz ich deklarowanie, oraz podstawowe operatory

KURS C/C++ WYKŁAD 8. Deklaracja funkcji informuje komplilator jaką wartość funkcja będzie zwracała i jakiego typu są jej argumenty.

Dynamiczny przydział pamięci w języku C. Dynamiczne struktury danych. dr inż. Jarosław Forenc. Metoda 1 (wektor N M-elementowy)

Laboratorium nr 10. Temat: Funkcje cz.2.

JĘZYKI PROGRAMOWANIA Z PROGRAMOWANIEM OBIEKTOWYM. Wykład 6

Tablice i funkcje. Marcin Makowski. 26 listopada Zak lad Chemii Teoretycznej UJ

Podstawy programowania w języku C++

tablica: dane_liczbowe

Podstawy programowania. Wykład 7 Tablice wielowymiarowe, SOA, AOS, itp. Krzysztof Banaś Podstawy programowania 1

Stałe i zmienne znakowe. Stała znakowa: znak

Zmienne i struktury dynamiczne

Podstawy programowania 1

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

Zajęcia nr 2 Programowanie strukturalne. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec

Podstawy programowania skrót z wykładów:

Podstawy programowania, Poniedziałek , 8-10 Projekt, część 1

Ćwiczenie nr 6. Poprawne deklaracje takich zmiennych tekstowych mogą wyglądać tak:

Warto też w tym miejscu powiedzieć, że w C zero jest rozpoznawane jako fałsz, a wszystkie pozostałe wartości jako prawda.

Tablice deklaracja, reprezentacja wewnętrzna

Lab 10. Funkcje w argumentach funkcji metoda Newtona. Synonimy nazw typów danych. Struktury. Tablice struktur.

main( ) main( void ) main( int argc, char argv[ ] ) int MAX ( int liczba_1, liczba_2, liczba_3 ) źle!

Wprowadzenie do programowania w języku C

Język C, tablice i funkcje (laboratorium, EE1-DI)

Typy wyliczeniowe Konwersje napis <-> liczba Struktury, unie Scanf / printf Wskaźniki

Typy złożone. Struktury, pola bitowe i unie. Programowanie Proceduralne 1

Laboratorium 6: Ciągi znaków. mgr inż. Leszek Ciopiński dr inż. Arkadiusz Chrobot dr inż. Grzegorz Łukawski

Funkcja, argumenty funkcji

Część 4 życie programu

Laboratorium 3: Tablice, tablice znaków i funkcje operujące na ciągach znaków. dr inż. Arkadiusz Chrobot dr inż. Grzegorz Łukawski

Ćwiczenie 5 z Podstaw programowania. Język C++, programy pisane w nieobiektowym stylu programowania. Zofia Kruczkiewicz

Operatory. Operatory bitowe i uzupełnienie informacji o pozostałych operatorach. Programowanie Proceduralne 1

Podstawy programowania w języku C++

Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1. Kraków 2013

Wskaźniki, funkcje i tablice

Programowanie I C / C++ laboratorium 02 Składnia pętli, typy zmiennych, operatory

ISO/ANSI C - funkcje. Funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje

Programowanie w C++ Wykład 4. Katarzyna Grzelak. 19 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 37

Ćwiczenie 4 z Podstaw programowania. Język C++, programy pisane w nieobiektowym stylu programowania. Zofia Kruczkiewicz

Proste typy zmiennych języka C++ *) Zapis 3.4 e-38 jest równoważny zapisowi 3,

Stałe, znaki, łańcuchy znaków, wejście i wyjście sformatowane

Struktura programu. Projekty złożone składają się zwykłe z różnych plików. Zawartość każdego pliku programista wyznacza zgodnie z jego przeznaczeniem.

Transkrypt:

Wskaźniki w C Anna Gogolińska

Zmienne Zmienną w C można traktować jako obszar w pamięci etykietowany nazwą zmiennej i zawierający jej wartość. Przykład: kod graficznie int a; a a = 3; a 3

Wskaźniki Wskaźnik to tylko adres w pamięci czyli wskazanie na określone miejsce w pamięci. Można sobie go wyobrażać jako strzełkę. Wskaźnik tworzymy poprzed dodanie przez nazwą zmiennej *. int *p; p

WAŻNE!!! Jeśli utworzyliśmy wskaźnik np. int *p; to: p to adres w pamięci! Wszelkie operacje na samym p (np. p++) to operacje na adresach pamięci! *p to element na który wskazuje wskaźnik! Zazwyczaj to jego chcemy modyfikować (a nie sam adres). Na przykład (*p)++ powoduje zwiększenie elementu wskazywanego przez p. Elementem zerowym ( zerem dla wskaźników ) jest wartość NULL, nazywana wskaźnikiem pustym. Wyzerowanie wskaźnika: p = NULL; /*dlaczego nie *p?*/

Wskaźniki Nowo utworzony wskaźnik wskazuje na nieokreślone miejsce w pamięci, często obszar do którego program nie ma prawa pisać. Wskaźnik który na razie na nic nie wskazuje dobrze jest wyzerować (przypisać NULL). Aby móc używać wskaźnika trzeba wyznaczyć/zarezerwać obszar pamięci na który on będzie wskazywać. Można to zrobić na dwa sposoby.

I - Przypisanie pod adres zmiennej Pierwszym sposobem przydzielenia pamięci dla wskaźnika jest przypisanie go pod adres zmiennej. int a; a a = 3; int *p; p = &a; p a 3 p a 3 Teraz zarówno pod a jak i pod *p mamy wartość 3.

Przypisanie pod adres zmiennej int a; a = 3; int *p; p = &a; a++; *p+=2; p p a 4 a 6

Przypisanie pod adres zmiennej W przykładzie wyżej na koniec zmienna ma wartość 6. Powyższa konstrukcja wydaje się nieprzydatna po co nam dwa obiekty, które wskazują na tą samą wartość? Użyteczne jest to jednak w przekazywaniu argumentów do funkcji. Normalnie do funkcji przekazywane są kopie wartości argumentów, operacje na tych wartościach nie są widziane poza funkcją. Aby rzeczywiście modyfikować wartości argumentów należy je przekazać przez wskaźnik (a w zasadzie do funkcji przekazać adres argumentu).

Funkcje i wskaźniki void skracanie(int* licz, int * mian) { int a = nwd(*licz, *mian); /*nwd() to inna funkcja zdefiniowana wyżej w kodzie*/ *licz = *licz / a; /*dlaczego nie licz = licz/a?*/ *mian = *mian / a; return; int main(){ int a = 10, b = 45; skracanie(&a, &b); return 0;

Funkcje i wskaźniki Funkcja z poprzedniego slajdu przyjmuje dwa argumenty, z których jeden jest licznikiem ułamka, a drugi mianownikiem ułamka i skraca je. Ponieważ operuje na wskaźnikach zmienione zastoną rzeczywiste wartości a i b, a nie ich kopie. Aby funkcja działała należy przekazać do niej adresy zmiennych a i b - poprzez operator &. W tym miejscu dochodzi do przypisania licz = &a i mian = &b. dlaczego nie licz = licz/a? taki zapis oznaczałby podzielenie adresu zmiennej, czyli numeru określającego blok pamięci i przypisanie go pod adres zmiennej. Wskaźnik licz wskazywałby wtedy jakiś zupełnie inny obszar pamięci.

II - Przydzielenie pamięci Innym sposobem przydzielenia pamięci dla wskaźnika jest wykonanie tego bezpośrednio (bez pośrednictwa zwykłej zmiennej). Służy do tego funkcja malloc i calloc z biblioteki stdlib.h. Przykład (w pierwszym przykładzie od razu przydzielamy pamięć, w drugim wpierw tworzymy wskaźnik, a pamięć przydzielamy później między tymi czynnościami mogą występować inne instrukcje): int * p = (int *)malloc(sizeof(int)); char * q; /*opcjonalnie inne instrukcje*/ q = (char *)malloc(sizeof(char));

malloc p = (int *)malloc(sizeof(int)) - na początku należy zrobić rzutowanie na typ wskaźnika dla jakiego przydzielmy pamięć, ponieważ funkcja malloc zwraca zawsze void*. p = (int *)malloc(sizeof(int)) argumentem dla funkcji malloc jest wielkość obszaru pamięci jaki chcemy przydzielić. Tu jest to rozmiar jednego inta. Wskazane jest użycie operatowa sizeof. Do obszaru przydzielonego przez funkcję malloc dostęp jest jedynie za pośrednictwem wskaźnika, np: int * p = (int *)malloc(sizeof(int)); *p = 10;

malloc i tablice Funkcja malloc nie musi zwracać obszaru pamięci równego wielkości jednej zmiennej. Można zwracać wielokrotności rozmiarów zmiennych. W ten sposób można deklarować tablice (w przykładzie niżej tablica długości n): int *t; /*opcjonalnie inne instrukcje*/ t = (int*)malloc(sizeof(int) * n)); Używjąc takiej definicji można tworzyć tablice dynamicznie wielkość tablicy jest ustalana w trakcie działania programu, np. podawana przez użytkownia (w przykładzie wyżej wartość n może być zczytywana między deklaracją wskaźnika, a wywołaniem funkcji malloc).

Calloc Funkcja calloc jest bardzo podobna do funkcji malloc, ma tylko nieco inną składnię. W przykładach dalej pojawiać się będzie malloc ale można go zastąpić również przez calloc. int * tab = (int*) calloc (i,sizeof(int)); Pierwszym argumentem funkcji jest ilość komórek pamięci które chcemy przydzielić (np. wielkość tablicy, albo 1 w przypadku pojedyńczej zmiennej). Drugim jest wielkość pojedyńczego elementu. W przykładzie powyżej przydzielamy pamięć dla tablicy intów wielkości i.

Tablice i wskaźniki Tablica w C jest wskaźnikiem. A dokładniej identyfikator tablicy jest wskaźnikiem na pierwszy jej element. Jeśli mamy tablice int tab[10] to tab jest adresem pierwszego (zerowego) elementu. Możemy się do tego elemetu odwołać używając tab[0] lub *tab. Oba sposoby operowania na tablicach: z użyciem [] czy z użyciem * są poprawne i równoważne. Można nawet je mieszać. Ponieważ tablica jest wskaźnikiem, nie stosuje się operatowa & w funkcji scanf, podczas wczytywania łańcucha znaków: char napis[20]; scanf( %s, napis);

Tablice i wskaźniki Zapis z użyciem * zamiast z [] stosuje się, kiedy funkcja ma przyjmować tablice jako argument lub ją zwracać, na przykład: char* funkcja(int* tab1, double* tab2) Na wskaźnikach można używać operatorów +, -, +=, -=, ++, --. Powodują one przesunięcie wskaźnika na następną komórkę pamięci (wielkości odpowiadającej typowi wskaźnika). Dzięki użyciu tych operatorów można iterować po tablicach po prostu przesuwając wskaźnik.

Tablice przykład 1 #include <stdio.h> int main(){ int tab[5], i, maks; printf( podaj elementy tablicy\n ); for(i = 0; i < 5; i++) scanf( %d, &tab[i]); maks = tab[0]; for(i = 1; i < 5; i++) if(maks < tab[i]) maks = tab[i]; printf( element najwiekszy: %d\n, maks); return 0;

Tablice przykład 2 #include <stdio.h> #include <stdlib.h> int main(){ int *tab, *pom, i, maks; tab = (int*)malloc(sizeof(int) * 5); pom = tab; printf( podaj elementy tablicy\n ); for(i = 0; i < 5; i++) { scanf( %d, tab); tab = pom; maks = *tab; for(i = 1; i < 5; i++){ if(maks < *tab) maks = *tab; printf( element najwiekszy: %d\n, maks); return 0; tab

Tablice przykład 2 #include <stdio.h> #include <stdlib.h> int main(){ int *tab, *pom, i, maks; tab = (int*)malloc(sizeof(int) * 5); pom = tab; printf( podaj elementy tablicy\n ); for(i = 0; i < 5; i++) { scanf( %d, tab); tab = pom; maks = *tab; for(i = 1; i < 5; i++){ if(maks < *tab) maks = *tab; printf( element najwiekszy: %d\n, maks); return 0; Zmienna pomocnicza w której przechowywany i zachowywany jest wskaźnik na początek tablicy, ponieważ wskaźnik tab jest później przesuwany na kolejne elemety. tab pom

Tablice przykład 2 #include <stdio.h> #include <stdlib.h> int main(){ int *tab, *pom, i, maks; tab = (int*)malloc(sizeof(int) * 5); pom = tab; printf( podaj elementy tablicy\n ); for(i = 0; i < 5; i++) { scanf( %d, tab); tab = pom; maks = *tab; for(i = 1; i < 5; i++){ if(maks < *tab) maks = *tab; printf( element najwiekszy: %d\n, maks); return 0; W pierwszej iteracji pętli tab wskazuje na zerowy element tablicy. Pod element ten wspisywana jest wartość podana przez użytkownia. Ponieważ tab jest wskaźnikiem nie jest potrzebne użycie &.

Tablice przykład 2 #include <stdio.h> #include <stdlib.h> int main(){ int *tab, *pom, i, maks; tab = (int*)malloc(sizeof(int) * 5); pom = tab; printf( podaj elementy tablicy\n ); for(i = 0; i < 5; i++) { scanf( %d, tab); tab = pom; maks = *tab; for(i = 1; i < 5; i++){ if(maks < *tab) maks = *tab; printf( element najwiekszy: %d\n, maks); return 0; pom tab Wskaźnik tab jest przesuwany o długość zmiennej int (ponieważ tab jest takiego typu) i wskazuje na kolejną wartość int w pamięci czyli na kolejny element tablicy. W ten sposób w pętli for wypełni/przejrzy się wszystkie elementy tablicy.

Tablice przykład 2 #include <stdio.h> #include <stdlib.h> int main(){ int *tab, *pom, i, maks; tab = (int*)malloc(sizeof(int) * 5); pom = tab; printf( podaj elementy tablicy\n ); for(i = 0; i < 5; i++) { scanf( %d, tab); tab = pom; maks = *tab; for(i = 1; i < 5; i++){ if(maks < *tab) maks = *tab; printf( element najwiekszy: %d\n, maks); return 0; W pom zapamiętany jest wskaźnik na początek tablicy. Teraz również zmienna tab wskazuje na ten początek. tab pom

Tablice przykład 2 #include <stdio.h> #include <stdlib.h> int main(){ int *tab, *pom, i, maks; tab = (int*)malloc(sizeof(int) * 5); pom = tab; printf( podaj elementy tablicy\n ); for(i = 0; i < 5; i++) { scanf( %d, tab); tab = pom; maks = *tab; for(i = 1; i < 5; i++){ if(maks < *tab) maks = *tab; printf( element najwiekszy: %d\n, maks); return 0; Do elementu tablicy można się odwołać jak do elementu wskazywanego przez wskaźnik, czyli z użyciem *.

Tablice - przykłady Oba przykłady działają tak samo. Pierwszy jest prostszy i krótszy w zapisie. Drugi jednak ma nad nim znaczną przewagę zamiast deklarować od razy wielkość tablicy można o nią zapytać użytkownika i stworzyć tablicę dynamicznie. Ponieważ oba podejścia do tablic można mieszać, w praktycznych zastosowaniach można utworzyć tablicę jako wskaźnik, a później traktować ją w sposób klasyczny (z użyciem []).

Częste błędy Odwoływanie się do wskaźnika do którego nie przydzielono pamięci. Na przykład: int *p; *p = 10; Mylenie samego wskaźnika (czyli adres) i elementu przez niego wskazywanego, np. w wywołaniach funkcji, iteracji po tablicy z użyciem wskaźnika. Przekroczenie wielkości tablicy wyjechanie wskaźnikiem za tablicę. Nie jest to kontrolowane przez kompilator.