Język C – zajęcia nr 9

Transkrypt

Język C – zajęcia nr 9
Język C – zajęcia nr 9
I. Operatory języka C – ciąg dalszy
Operator indeksowania
Dwuargumentowy operator indeksowania [ ] jest operatorem sumowania: wylicza
sumę swoich argumentów i dostarcza wartości obszaru pomięci, na który wskazuje
uzyskana suma. Jednym z argumentów musi być wyrażenie mające wartość
wskaźnika, a drugim wyrażenie o wartości całkowitej. Wyrażenie postaci:
a[b]
ma wartość:
*( a+b )
Operator indeksowania umożliwia między innymi dostęp do elementów tablicy.
Ponieważ nazwa tablicy jest równocześnie stałym wskaźnikiem na jej początek,
wartością wyrażenia:
tab [ k ]
jest wartość elementu o numerze k tablicy tab.
Uwaga: Z racji przemienności operacji indeksowania wyrażenie tab[k] jest w
pełni równoważne wyrażeniu k[tab], czyli x[5] ma tę samą wartość, co 5[x].
Operator sizeof
Użycie operatora sizeof może mieć formę:
sizeof zmienna
gdzie zmienna jest nazwą zmiennej dowolnego typu lub formę:
sizeof ( typ )
gdzie typ jest nazwą typu.
Wartością wyrażeń z operatorem sizeof jest liczba bajtów przeznaczonych w pamięci
dla podanego jako argument obiektu lub typu.
Wprowadź i uruchom program, zinterpretuj wyniki:
#include <stdio.h>
void main()
{
char a;
int b;
long int c;
float d;
double e;
long double f;
int g[12];
printf("\n%d %d %d %d %d %d %d",sizeof a, sizeof b,
sizeof c, sizeof d, sizeof e, sizeof f, sizeof g);
printf("\n%d %d",sizeof(int), sizeof(double));
}
1 2 4 4 8 10 24
2 8
Operator adresu
Jednoargumentowy operator & zastosowany do l-wartości lub nazwy funkcji
dostarcza adresu swojego argumentu. Wyrażenie postaci:
& obiekt
ma wartość adresu argumentu obiekt.
Operator wyłuskania
Jednoargumentowy operator wyłuskania * dostarcza wartości (zawartości) obszaru
pamięci na który wskazuje argument operatora.
Jeżeli wartością zmiennej p jest wskaźnik na obiekt q, to wyrażenie *p ma
wartość obiektu q.
Operator rzutowania
Jawne wymuszenie konwersji typów dokonywane jest poprzez operator rzutowania
mający postać:
( typ )
gdzie typ jest nazwą typu.
Wyrażenie:
( typ ) arg
ma wartość, jaka powstaje z wartości argumentu arg przekształconej do typu typ.
Wprowadź i uruchom program, zinterpretuj wyniki:
#include <stdio.h>
#include <math.h>
void main()
{
float x;
scanf("%f",&x);
printf("\n%f",sqrt(x));
printf("\n%d",(int)sqrt(x));
}
18.4
4.289522
4
KLAWIATURA 18.4
Priorytety i wiązania operatorów (wykaz kompletny):
Priorytet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Operator
( )
[ ]
.
->
+
~
!
++
-*
&
sizeof
( )
*
/
%
+
<<
>>
<
<=
>
>=
==
!=
&
^
|
&&
||
?:
=
+=
-=
*=
/=
%=
&=
|=
<<=
>>=
^=
,
Wiązanie
Lewostronne
Lewostronne
Lewostronne
Lewostronne
Prawostronne
Prawostronne
Prawostronne
Prawostronne
Prawostronne
Prawostronne
Prawostronne
Prawostronne
Prawostronne
Prawostronne
Lewostronne
Lewostronne
Lewostronne
Lewostronne
Lewostronne
Lewostronne
Lewostronne
Lewostronne
Lewostronne
Lewostronne
Lewostronne
Lewostronne
Lewostronne
Lewostronne
Lewostronne
Lewostronne
Lewostronne
Lewostronne
Prawostronne
Prawostronne
Prawostronne
Prawostronne
Prawostronne
Prawostronne
Prawostronne
Prawostronne
Prawostronne
Prawostronne
Prawostronne
Prawostronne
Lewostronne
Nazwa operatora
Wywołanie funkcji
Indeksowanie
Wybór składowej
Wybór wskaźnikowy składowej
Jednoargumentowy plus
Jednoargumentowy minus
Bitowa negacja
Logiczna negacja
Inkrementacja
Dekrementacja
Wyłuskanie
Pobranie adresu
Rozmiar
Rzutowanie
Mnożenie
Dzielenie
Modulo
Dodawanie
Odejmowanie
Bitowe przesunięcie w lewo
Bitowe przesunięcie w prawo
Relacja mniejszy
Relacja mniejszy lub równy
Relacja większy
Relacja większy lub równy
Równy
Różny
Bitowa koniunkcja
Bitowa różnica symetryczna
Bitowa alternatywa
Logiczna koniunkcja
Logiczna alternatywa
Warunek
Przypisania
Złożony przypisania
Złożony przypisania
Złożony przypisania
Złożony przypisania
Złożony przypisania
Złożony przypisania
Złożony przypisania
Złożony przypisania
Złożony przypisania
Złożony przypisania
Połączenie
Uwaga: Wiązanie prawostronne mają jedynie operatory: jednoargumentowe,
warunku i przypisania. Pozostałe operatory mają wiązanie lewostronne.
Uwaga: Pozostałe operatory: bitowe, operator składowej, wywołania funkcji oraz
połączenia – zostaną omówione w dalszej części kursu.
II. Dynamiczna alokacja pamięci
Język C umożliwia tworzenie tablic o dowolnym rozmiarze, określanym w trakcie
wykonywania programu. Jest to możliwe dzięki dynamicznej alokacji pamięci z
zastosowaniem wskaźników.
Zmienne lokalne zdefiniowane w programie wewnątrz tzw. bloku (blok funkcyjny
zawiera ujęte w nawiasy klamrowe { } instrukcje wykonywane przy wywołaniu funkcji)
przechowywane są na tzw. stosie (ang. stack). Zmienne takie powstają, gdy program
wchodzi do bloku, w którym są one zadeklarowane; natomiast w momencie, gdy
program opuszcza ten blok, zmienne te są likwidowane a przeznaczona na nie
pamięć jest zwalniana. Rozmiar tablic musi być znany w momencie kompilacji - aby
kompilator zarezerwował odpowiednią ilość pamięci. Dostępny jest jednak inny
rodzaj rezerwacji (czyli alokacji) pamięci – tzw. dynamiczna alokacja pamięci. Jest
to alokacja na stercie (ang. heap). Sterta to obszar pamięci wspólny dla całego
programu, przechowywane są w nim zmienne, których czas życia nie jest związany z
poszczególnymi blokami. Należy samemu rezerwować dla nich miejsce i to miejsce
zwalniać, ale dzięki temu można to zrobić w dowolnym momencie działania
programu.
Operacje na stercie zajmują więcej czasu niż analogiczne działania na stosie;
ponadto zmienna zajmuje na stercie więcej miejsca niż na stosie. Należy zatem
używać dynamicznej alokacji tam, gdzie jest ona rzeczywiście potrzebna - dla
obiektów, których rozmiaru nie jesteśmy w stanie przewidzieć na etapie kompilacji
lub ich żywotność ma być niezwiązana z wyłącznie z pojedynczym blokiem.
Podstawową funkcją do alokacji pamięci jest funkcja malloc. Zwraca ona wskaźnik
do zaalokowanego obszaru.
malloc(rozmiar_pamieci_w_bajtach)
Definicje funkcji związanych z dynamiczną alokacją pamięci znajdują się w pliku
stdlib.h (należy go dołączyć za pomocą odpowiedniej dyrektywy preprocesora).
Przykład: należy stworzyć n-elementową tablicę liczb typu double:
int n;
double *tab;
scanf(“%d”,&n);
tab = (double*) malloc(n * sizeof(*tab));
*(tab+n-1)=2.;
…………
Należy także sprawdzić, czy funkcja malloc nie zwróciła wartości NULL - tak się
dzieje, gdy zabrakło pamięci (lub jeżeli jako argument funkcji podano zero).
Jeśli zaalokowany obszar pamięci nie będzie już więcej potrzebny, należy go
zwolnić, aby był dostępny dla innych procesów. Do zwolnienia obszaru należy
zastosować funkcję free(), która posiada jeden argument - wskaźnik, który
wygenerowała funkcja malloc().
free (addr);
Należy pamiętać o zwalnianiu niepotrzebnej pamięci, w przeciwnym wypadku
może jej zabraknąć. Należy też uważać, by nie zwalniać dwa razy tego samego
miejsca. Błędem jest też zwalnianie miejsca, które nie zostało wcześniej
zaalokowane!
Po wywołaniu free wskaźnik nie zmienia wartości, aby przypadkiem go wtedy nie
użyć, można mu przypisać wartość NULL.
scanf(“%ld”,&n);
tab = (double*) malloc(n * sizeof(*tab)));
if (tab==NULL) {printf(“\nBLAD!!”); exit(1);};
…………
free(tab); tab=NULL;
Jeżeli istnieje potrzeba zmiany rozmiaru już przydzielonego bloku pamięci, można
zastosować funkcję realloc:
tab = realloc(tab, 2*n*sizeof *tab);
Funkcja ta zwraca wskaźnik do bloku pamięci o pożądanej wielkości (lub NULL gdy
zabrakło pamięci). Uwaga - może to być inny wskaźnik. Jeśli zażądamy zwiększenia
rozmiaru a za zaalokowanym aktualnie obszarem nie będzie wystarczająco dużo
wolnego miejsca, funkcja znajdzie nowe miejsce i przekopiuje tam starą zawartość.
Do dynamicznej alokacji pamięci może też posłużyć funkcja calloc(). Ma ona
dwa argumenty: liczbę elementów tablicy oraz wielkość pojedynczego elementu.
Podstawową różnicą pomiędzy funkcjami malloc() i calloc() jest to, że
calloc() zeruje wartość przydzielonej pamięci (do wszystkich bajtów wpisuje 0).
tab = (int *) calloc(n, sizeof(int));
III. Zadania
1. Wczytaj z klawiatury ciąg n liczb rzeczywistych i wypisz te liczby w
kolumnie w kolejności odwrotnej. Zastosuj dynamiczną alokację pamięci.
2. Wczytaj z klawiatury ciąg n znaków i oblicz, ile razy wystąpił w tym
ciągu ostatni (n-ty) znak.

Podobne dokumenty