ĆWICZENIE 1 Wskaźniki
Celem ćwiczenia jest zapoznanie z podstawowymi operacjami na wskaźnikach.
I. PRZEBIEG ĆWICZENIA
1. Wprowadzić program ilustrujący podstawowe operacje wskaźnikach:
#include <stdio.h>
void main(void) { int x;
int * ptrX; /*ptrX jest wskaźnikiem do zmiennej typu
int=ptrX przechowuje adres (dowolnej) zmiennej typu int*/
x=3;
ptrX = &x; {ptrX jest równe Adresowi zmiennej x}
printf("%d\n",x); {Wynik: 3}
printf("%d\n",*ptrX); {Wynik: 3. *ptrX oznacza: Wykonaj operację na tej zmiennej, na którą
wskazuje ptrX}
*ptrX=86; {Ponieważ ptrX wskazuje na x, więc (*ptrX) i x to dokładnie to samo.}
printf("%d\n",x); {Wynik: 86}
printf("%d\n",*ptrX); {Wynik: 86}
}
2. Wprowadzić inny program ilustrujący podstawowe operacje wskaźnikach:
#include <stdio.h>
void main(void) { int x;
int *ptrX;
int *ptrY;
x=3;
ptrX=&x;
ptrY=&x;
*ptrY=2; /*Tutaj *ptrY przyjmie wartość 2. Ponieważ ptrY=&x (ptrY jest równe adresowi zmiennej x), więc x również przyjmie wartość 2. Ponieważ
*ptrX=x, więc *ptrX również będzie równało się dwa!*/
printf("%d\n", x); /*Wynik: 2*/
printf("%d\n", *ptrX); /*Wynik: 2*/
printf("%d\n", *ptrY); /*Wynik: 2*/
}
3. Wprowadzić program ilustrujący przydział i zwalnianie pamięci dla prostych zmiennych:
#include <stdio.h>
void main(void) { int *ptrX;
ptrX = new int; /*Tworzona jest nowa zmienna dynamiczna, na którą wskazuje wskaźnik ptrX. Dostęp do zmiennej dynamicznej możliwy jest tylko poprzez wskaźnik!*/
*ptrX=3; /* Przypisanie wartości zmiennej dynamicznej, na którą wskazuje ptrX. Zmienną *ptrX (gwiazdka pe te er iks) można traktować jak każdą inną zmienną typu int!*/
printf("%d\n", *ptrX); /*Wynik: 3*/
delete ptrX; /*Pamięć dla zmiennej *ptrX została zwolniona. */
ptrX = NULL; /*Zalecane, gdyż teraz odwołanie *ptrX zostanie wykryte przez kompilator jako błąd. Ułatwia to usuwanie błędu odwołania do nieistniejącej zmiennej*/
/*UWAGA: JAK KTOŚ MI W TYM MIEJSCU NAPISZE:
printf(„%d\n”, *ptrX) TO POSTAWIĘ MU DWÓJĘ NA WEJŚCIÓWCE!
Pamięć dla *ptrX została zwolniona, więc BEZWZGLĘDNIE,
CAŁKOWICIE, ABSOLUTNIE ZABRONIONE JEST ODWOŁYWANIE
SIĘ DO ZMIENNEJ, KTÓREJ PAMIĘĆ ZOSTAŁA ZWOLNIONA!!!
PtrX NIE WSKAZUJE NA ŻADNĄ SENSOWNĄ ZMIENNĄ
(PRZECIEŻ PO TO WYKONANO delete ptrX). Oczywiście nadal możliwe są operacje na wskaźniku ptrX – jest to przecież zmienna statyczna (deklarowana przez int *ptrX). Jeśli ptrX nie wskazuje na istniejącą zmienną (wartością ptrX nie jest adres istniejącej
zmiennej), obowiązuje CAŁKOWITY ZAKAZ odwoływania się do niej. */
}
4. Wprowadzić program ilustrujący dynamiczne tworzenie rekordów:
#include <stdio.h>
/*Deklaracja struktury typu TDane*/
struct TDane { int x;
int y;
int p;
}; /*Uwaga na średnik tutaj!*/
void main(void) {
TDane Dane; /*Zmienna statyczna typu strukturalnego TDane*/
TDane * ptrDane; /*Wskaźnik do zmiennych typu TDane*/
Dane.x = 1; /*Przypisanie wartości 1 do pola x struktury - nic nowego...*/
ptrDane = &Dane; /* teraz ptrDane wskazuje na CAŁĄ strukturę, */
(*ptrDane).y=2; /*dlatego trzeba użyć operatora "." (kropka) do odwołania się do poszczególnych pól - tak, jak zwykle.
ptrDane jest wskaźnikiem do struktury, więc
*ptrDane jest strukturą, więc (*ptrDane).y jest polem y tej
struktury. Oczywiście ptrDane.x (bez gwiazdki "*") jest błędne, gdyż ptrDane jest WSKAŹNIKIEM do struktury, a nie strukturą.
Ponieważ zapis (*ptrDane).y jest skomplikowany, więc wymyślono:*/
ptrDane->p=3;
//ptrDane.p
//jest TYM SAMYM, co //(*ptrDane).p
//. Jest to po prostu szybszy sposób odwołania się do pola //struktury.
printf("%d\n", ptrDane->x); /*Wynik: 1*/
}
5. Wprowadzić program ilustrujący dynamiczne tworzenie struktur:
#include <stdio.h>
struct TDane { int x;
int y;
int p;
};
void main(void) { TDane * ptrDane;
ptrDane = new TDane; /*Utworzenie zmiennej dynamicznej typu TDane i przypisanie wskaźnikowi ptrDane adresu tej nowej zmiennej*/
printf("Podaj x:");
scanf("%d",&(ptrDane->x)); /*przy scanf jak zwykle trzeba dać ampersand "&"... Nawiasy zwiększają czytelność. */
printf("%d\n", ptrDane->x);
delete ptrDane; /*Zwolnienie pamięci zajmowanej przez *ptrDane. Od teraz odwołanie do *ptrDane jest błędne*/
ptrDane = NULL;
}