PODSTAW PROGRAMOWANIA WYKŁAD 6 WSKAŹNIKI Wskaźnik

Transkrypt

PODSTAW PROGRAMOWANIA WYKŁAD 6 WSKAŹNIKI Wskaźnik
PODSTAW PROGRAMOWANIA WYKŁAD 6
WSKAŹNIKI
Wskaźnik  jest zmienną, która zawiera adres (wskazanie) początku
dowolnego obszaru w pamięci komputera,
(np. może być to adres obszaru danych lub adres kodu
programu)
Ogólna postać definicji wskaźnika:
typ_danych  identyfikator wskaźnika ;
Podstawowe zastosowania wskaźników to:
1. przekazywanie przez wskaźnik zmiennej jako argumentu funkcji,
2. dynamiczny przydział pamięci,
3. operacje arytmetyczne na wskaźnikach.
4. Wskaźniki używane do dostępu do tablic
1. przekazywanie przez wskaźnik zmiennej jako argumentu funkcji,
#include <stdio.h>
int wartosc( int x );
void wskaznik (int *x);
int main()
{
int x = 1;
int y;
y = wartosc(x);
printf("Wartosc x po wywolaniu funkcji wartosc: %d\n", x);
wskaznik(&x);
printf("Wartosc x po wywolaniu funkcji wskaznik: %d\n", x);
return 0;
}
int wartosc( int x )
{
x++;
return x;
}
void wskaznik (int *x)
{
(*x)++;
}
#include<stdio.h>
#include<stdlib.h>
void f1(int x);
void f2(int* x);
void f3(int** x);
void f4(int& x);
int main()
{
int i,j,*k,*l,*m,n;
k=(int*)malloc(sizeof(int));
l=(int*)malloc(sizeof(int));
m=(int*)malloc(sizeof(int));
i=j=*k=*l=*m=n=2;
(*m)--;
f1(i);
f2(&j);
f2(k);
f3(&l);
f4(n);
printf("%d\n%d\n%d\n%d\n%d",i,j,*k,*l,n);
free(k);
free(l);
free(m);
return 0;
}
void f1(int x)
{
x--;
return;
}
void f2(int* x)
{
(*x)++;
return;
}
void f3(int** x)
{
*x+=sizeof(int);
return;
}
void f4(int& x)
{
x*=2;
return;
}
2. dynamiczny przydział pamięci,
malloc() (stdlib.h) – przydział n bajtów pamięci
void * memcpy ( void * destination, const void * source, size_t num );
/* memcpy example */
#include <stdio.h>
#include <string.h>
struct {
char name[40];
int age;
} person, person_copy;
int main ()
{
char myname[] = "Pierre de Fermat";
/* using memcpy to copy string: */
memcpy ( person.name, myname, strlen(myname)+1 );
person.age = 46;
/* using memcpy to copy structure: */
memcpy ( &person_copy, &person, sizeof(person) );
printf ("person_copy: %s, %d \n", person_copy.name,
person_copy.age );
return 0;
}
int memcmp ( const void * ptr1, const void * ptr2, size_t num
);
/* memcmp example */
#include <stdio.h>
#include <string.h>
int main ()
{
char buffer1[] = "DWgaOtP12df0";
char buffer2[] = "DWGAOTP12DF0";
int n;
n=memcmp ( buffer1, buffer2, sizeof(buffer1) );
if (n>0) printf ("'%s' is greater than
'%s'.\n",buffer1,buffer2);
else if (n<0) printf ("'%s' is less than
'%s'.\n",buffer1,buffer2);
else printf ("'%s' is the same as '%s'.\n",buffer1,buffer2);
return 0;
}
void * memset ( void * ptr, int value, size_t num );
void * memmove ( void * destination, const void * source,
size_t num );
memmove example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "memmove can be very useful......";
memmove (str+20,str+15,11);
puts (str);
return 0;
}
Ze wskaźnikami i adresami związane są dwa operatory:
 operator referencji & zwracający adres zmiennej podanej po prawej stronie
tego operatora.
 operator dereferencji  identyfikujący obszar wskazywany przez wskaźnik
podany po prawej stronie tego operatora.
int liczba ;
int wskaźnik ;
wskaznik = &liczba;
wskaźnik = 10;
// przypisanie zmiennej wskaźnik
// adresu zmiennej liczba
// przypisanie 10 zawartości zmiennej
// wskazywanej przez wskaźnik
// tutaj równoważne liczba = 10
Arytmetyka wskaźników
Na wskaźnikach mogą być wykonywane następujące operacje:
* przypisania ( = )
wsk = wskaznik_zmiennej_lub_obszaru_pamięci ;
(w przypadku niezgodności typów konieczne jest dokonanie konwersji
typu)
* operacje porównania ( ==, !=, <, >, <=, >= ):
wsk_1 == wsk_2 // sprawdzenie czy zmienne zawierają te same adresy
wsk_1 < wsk_2 // czy zmienna wsk_1 zawiera adres mniejszy
// od adresu zawartego w zmiennej wsk_2
* operacje powiększania lub pomniejszania wskaźnika ( +, -, ++, --, +=, -= )
o liczbę całkowitą (tylko dla wskaźników zdefiniowanych)
- powiększenie (pomniejszenie) wskaźnika o wartość N powoduje
wyznaczenie adresu przesuniętego o:
N - sizeof( typ_zmiennej_wskazywanej )
//Program 4
#include <stdio.h>
void main()
{
char i[3]={5,6,7},*wskaznik;
wskaznik=&(i[0]);
*wskaznik/=2;
wskaznik++;
(*wskaznik)+=9;
wskaznik++;
(*wskaznik)*=13;
printf("%d %d %d",i[0],i[1],i[2]);
return;
}
#include <stdio.h>
void main()
{
char i[3]={5,6,7},*wskaznik;
wskaznik=&(i[0]);
*wskaznik/=2;
wskaznik++;
(*wskaznik)+=9;
wskaznik++;
(*wskaznik)*=13;
printf("%d %d %d",i[0],i[1],i[2]);
return;
}
Najczęściej arytmetykę wskaźników stosuje się do dynamicznych
odpowiedników tablic .
Najczęstszym i najważniejszym zastosowaniem operacji
arytmetycznych jest przeglądanie (iterowanie) struktur danych — w
szczególności tablic/łańcuchów znaków. Wykorzystuje się do tego
celu głównie operator inkrementacji ++. Do wskaźników można też
dodawać dowolną liczbę całkowitą, a także odejmować od nich
dowolną liczbę całkowitą. Dla przykładu zdefiniujemy wskaźnik, do
którego przypiszemy adres początku tablicy.
int *wskaznik = tablica; // — trzeba pamiętać, że zapis tablica jest
równoważny z &tablica[0], czyli oznacza adres jej początku
#include <stdio.h>
#include <string.h>
void odwrocenie (char *s);
int main()
{
char ciag_znakow[20] = "Rychu ma bimber";
odwrocenie(ciag_znakow);
printf("Ciag znakow po odwroceniu: %s\n", ciag_znakow);
return 0;
}
void odwrocenie(char *s)
{
char *wsk = s + strlen(s)-1;
char temp;
for (;wsk>s;wsk--,s++)
{
temp = *s;
*s = *wsk;
*wsk = temp;
}
}