• Nie Znaleziono Wyników

zmienne – stanowią abstrakcję

N/A
N/A
Protected

Academic year: 2021

Share "zmienne – stanowią abstrakcję "

Copied!
32
0
0

Pełen tekst

(1)

ZMIENNE

(2)

zmienne – stanowią abstrakcję

komórek pamięci: programista może

przechowywać dane w pamięci, nie

martwiąc się o techniczne szczegóły

(np. przydział pamięci).

(3)

Nazewnictwo zmiennych

Dozwolone znaki. Tradycyjnie: litery, cyfry i zwykle znak podkreślenia.

Ale np. najnowsza wersja języka Ada (2005) przewiduje użycie dowolnych znaków z

zestawu Unicode.

Zwykle nazwa zmiennej musi zaczynać się literą.

Maksymalna liczba znaków nazwy jest zwykle duża, np. 255.

Rozróżnianie wielkich i małych liter (C, C++ i pochodne języki, jak np. Java, C#

rozróżniają)

(4)

Cechy zmiennej

(5)

1. Nazwa zmiennej

Nie każda zmienna ma nazwę: np. tworząc zmienne dynamiczne w C (malloc)

tworzymy zmienną bez nazwy (nazwę ma użyty wskaźnik, ale nie sama zmienna).

Tablice to zbiór wielu zmiennych tego samego typu, tablica zwykle posiada

nazwę, więc możemy ją też traktować jako pojedynczą zmienną tablicową (wektor czy macierz)

(6)

2. Adres

Adres to numer komórki pamięci, gdzie zmienna jest składowana

(zależnie od typu może być to więcej komórek, adres opisuje pierwszą z nich)

Program może zawierać dwie

zmienne o tej samej nazwie, ale nie mające ze sobą nic wspólnego, np.

dwie zmienne lokalne o nazwie i w

dwóch różnych podprogramach.

(7)

2. Adres (cd.)

Ta sama zmienna lokalna może mieć

różne adresy w czasie różnych wywołań tego samego podprogramu.

Nie ma więc jednoznacznej

odpowiedniości między nazwą a adresem.

Bieżący adres zmiennej zwany jest l-

wartością (l-value); to określenie bierze się stąd, że właśnie adres zmiennej jest potrzebny przy wpisywaniu wartości do zmiennej (po lewej stronie instrukcji

przypisania).

(8)

Aliasowanie

To sytuacja, gdy do tej samej komórki pamięci można dotrzeć za pomocą dwóch różnych nazw.

Tak jest np. wtedy, gdy dwa wskaźniki ustawimy na ten sam adres:

Aliasowanie może prowadzić do przeoczeń i niejasności w kodzie, lepiej więc go unikać.

(9)

3. Wartość

Jest to po prostu zawartość komórki (komórek) pamięci związanej z daną zmienną.

Zwana niekiedy r- wartością (r-value) ponieważ to wartość zmiennej

odczytujemy, gdy zmienna występuje

po prawej stronie przypisania.

(10)

4. Typ

Typ to zbiór dopuszczalnych wartości, jakie zmienna może przyjmować.

Z typem wiąże się również zbiór operacji dopuszczalnych dla danej zmiennej.

Przykład: typ int w języku C najczęściej oznacza liczbę całkowitą ze znakiem zapisaną na 32

bitach (jeden z nich jest przeznaczony na znak).

Zbiór dopuszczalnych wartości: (-231;231].

Przykładowe operacje: dodawanie, odejmowanie, itp.

Gdy mówimy o zmiennych w reprezentacji

zmiennopozycyjnej, typ określa też precyzję, z jaką liczby są reprezentowane.

(11)

Wiązania

Różne byty i atrybuty, w pewnym

momencie zostają ze sobą powiązane.

Rzecz dotyczy bardzo rozmaitych

„bytów” takich jak zmienna, operator,

wywołania podprogramu i cech takich jak wartość, typ, adres.

Przykładowo, deklaracja zmiennej

powoduje związanie zmiennej z typem, zaś wykonanie instrukcji podstawienia powoduje powiązanie zmiennej z (nową) wartością.

(12)

Wiązania statyczne i dynamiczne

Wiązania dzielimy na dwie klasy.

Wiązania statyczne to te, które

następują przed wykonaniem programu i nie zmieniają się w trakcie jego

działania. Praktycznie następują „w czasie kompilacji programu”.

Wiązania dynamiczne to te, które następują lub zmieniają się w trakcie działania programu. Praktycznie

następują „w czasie wykonania programu”.

(13)

Wiązanie typu

Każda zmienna musi zostać związana z typem przed pierwszym użyciem w programie.

Rozpatrujemy dwa aspekty tej sprawy:

1. Jak określamy ów typ?

2. Kiedy następuje wiązanie?

(14)

1. Jak określamy typ zmiennej?

We współczesnych językach zazwyczaj mamy jawną deklarację.

Bywają też deklaracje niejawne, np. pierwsze użycie zmiennej może stanowić deklarację.

W przypadku deklaracji niejawnych konwencja nazewnictwa zmiennej może określać typ. W Fortranie pierwsza litera nazwy wyznaczała typ zmiennej, chyba że zmienna została

zadeklarowana jawnie. W Perlu „zasada pierwszego znaku” jest obligatoryjna.

Występuje także mechanizm wnioskowania o typie z kontekstu, np. w języku ML i Haskellu.

(15)

2. Kiedy następuje wiązanie zmiennej z typem?

Deklaracje zmiennych dają wiązanie statyczne.

Gdy zmienna jest wiązana z typem przy pierwszym podstawieniu pod nią

wartości, (np. w PHP i JavaScripcie) jest to wiązanie dynamiczne.

Wiązanie dynamiczne gwarantuje elastyczność, ale ma dwie wady: jest

kosztowne (trzeba dynamicznie sprawdzać typ) i utrudnia wykrywanie błędów (kompilator ma małe szanse wykryć niezgodność typów).

(16)

Wiązanie pamięci

Pojęcia związanych z wiązaniem pamięci:

Okres życia zmiennej to czas, w którym jest ona związana z konkretnym miejscem w

pamięci.

Alokacja (przydział) pamięci oznacza pobranie bloku pamięci odpowiedniej

wielkości z puli wolnej pamięci i związanie go ze zmienną.

Dealokacja (zwolnienie) pamięci oznacza unicestwienie wiązania bloku pamięci ze

zmienną i oddanie go do puli wolnej pamięci.

Okres życia zmiennej to czas pomiędzy alokacją a dealokacją.

(17)

Cztery kategorie zmiennych, związane z ich okresem życia:

1.

Statyczne — mówimy wówczas o zmiennych statycznych

2.

Dynamiczne na stosie —

najczęściej mówi się o zmiennych automatycznych lub po prostu

lokalnych

3.

Dynamiczne na stercie, jawne.

4.

Dynamiczne na stercie, niejawne.

(18)

1. Zmienne statyczne

Wiązane z miejscem w pamięci przed

rozpoczęciem wykonania programu; wiązanie to nie zmienia się w trakcie wykonania.

Zaleta: Efektywne, ze względu na bezpośrednie adresowanie.

Wada: Mało elastyczne, nie mogą być

używane do obsługi wywołań rekurencyjnych.

Przykład: Zmienne globalne oraz zmienne zadeklarowane jako static w języku C.

Uwaga: W językach obiektowych takich jak C++, C# i Java deklaracja zmiennej z użyciem static zwykle oznacza coś innego.

(19)

2. Zmienne dynamiczne na stosie

Wiązane z pamięcią w chwili, gdy wykonanie programu dociera do ich deklaracji. (dynamicznie)

Pamięć dla nich jest przydzielana na stosie.

Pamięć zwalniana, gdy kończy się wykonanie bloku zawierającego daną zmienną.

Dla typowych zmiennych prostych (całkowite,

zmiennopozycyjne) wszystkie atrybuty z wyjątkiem pamięci są wiązane statycznie.

Zalety: Mogą być używane w wywołaniach rekurencyjnych.

Wady: Mniejsza efektywność ze względu na pośrednie

adresowanie, narzut związany z alokacją i dealokacją, brak

„historii” (każde wywołanie podprogramu tworzy nową instancję zmiennych).

Przykład: Zmienne lokalne w funkcjach w języku C i w metodach w Javie.

(20)

3. Zmienne dynamiczne na stercie, jawne

Alokowane przez programistę w trakcie wykonania programu za pomocą jawnych poleceń, np. new, malloc.

Dealokowane również jawnie (w C i C++ za pomocą free i delete) lub niejawnie poprzez mechanizm

odśmiecania (Java, C#).

Nie mają nazwy; dostępne są poprzez wskaźnik lub referencję.

Zalety: Mogą być używane do tworzenia dynamicznych struktur danych, np. list wiązanych i drzew.

Wady: Niska efektywność z powodu pośredniego trybu adresowania i skomplikowanego zarządzania stertą.

Duże ryzyko nadużyć ze strony nieostrożnego programisty.

(21)

4. Zmienne dynamiczne na stercie, niejawne

Alokowane i dealokowane niejawnie w trakcie wykonania programu w chwili wykonania podstawienia.

Przykład: Napisy i tablice w Perlu.

Zalety : Elastyczność posunięta do granic.

Wady : Wysoki koszt, związany z dynamicznym przechowywaniem

atrybutów. Trudne wykrywanie błędów.

(22)

Operatory i operandy

Operator wykonuje jakąś czynność przy pomocy dostarczonych operandów.

Podprogramy będziemy traktowali jako operatory, których operandami

parametry.

Instrukcję przypisania będziemy uważali za operację dwuargumentową, której operandami są lewa i prawa strona

przypisania.

(23)

Sprawdzanie zgodności typów

Sprawdzanie zgodności typów to

sprawdzenie, czy typy operandów są odpowiednie.

Określenie „odpowiedni (lub zgodny) typ”

oznacza typ bezpośrednio dozwolony w danym kontekście lub typ, który jest

dozwolony po zastosowaniu niejawnej konwersji typu narzuconej przez reguły języka programowania.

Błąd typu to użycie operatora z

operandem nieodpowiedniego typu.

(24)

Niejawna konwersja typu - przykład

W poniższym fragmencie wartość zmiennej j jest automatycznie

zamieniana z typu int na float i wykonywane jest dodawanie

zmiennopozycyjne.

float x, y;

int j;

x = y + j;

(25)

Kiedy następuje sprawdzanie zgodności typów?

Jeśli wiązanie typów jest statyczne, to sprawdzanie zgodności typów na ogół także może być statyczne, tzn. w czasie kompilacji.

Jeśli natomiast wiązanie typów jest

dynamiczne, to sprawdzanie zgodności typów musi być dynamiczne.

Statyczne sp. zg. t. jest korzystniejsze, ponieważ potencjalnie daje programiście więcej informacji.

(26)

Języki silnie typowane

Język nazywamy silnie typowanym, jeśli błędy typu są w nim zawsze wykrywane.

Zaletą silnego typowania jest możliwość wykrywania wielu pospolitych błędów.

Ada, C# i Java są „niemal” silnie typowane - odstępstwo to jawna konwersja typów.

Pascal nie jest silnie typowany ze względu na tzw. unie (nazywane tam wariantami w rekordzie).

C i C++ zdecydowanie nie są silnie typowane. Można w nich np. uniknąć

sprawdzania typów parametrów, występują tam też unie oraz niejawne konwersje typu.

(27)

Niejawne konwersje typu powodują, że np. błędne podstawienia mogą

formalnie nie być błędami typu.

Silne typowanie służy wykrywaniu błędów.

Silne typowanie bez konwersji sprzyja niezawodności (kosztem wygody

programisty).

(28)

Jak zdefiniować zgodność typów?

Dwie metody:

1.

zgodność nazwy

2.

zgodność struktury

(29)

1. Zgodność nazwy

Dwie zmienne uznajemy za zgodne co do typu, jeśli zostały zdefiniowane w tej samej deklaracji lub jeśli do ich

zadeklarowania użyto tej samej nazwy typu.

Łatwe w implementacji, ale bardzo restrykcyjne.

Przykład: Podzakresy typu całkowitego nie są z nim zgodne.

(30)

2. Zgodność struktury

Dwie zmienne uznajemy za zgodne co do typu, jeśli mają taką samą strukturę.

Problem: Nie da się rozróżnić typów o takiej samej strukturze, nawet jeśli w naszym zamierzeniu służą zupełnie różnym celom.

np. odległość wyrażona w dwóch różnych jednostkach jeżeli jest przechowywana w zmiennych typu float to jest zgodna co do struktury (niepożądane).

(31)

Typy pochodne

Typ pochodny to nowy typ oparty na typie już istniejącym.

Dziedziczy wszystkie własności typu bazowego.

Zakłada się, że nie jest zgodny z typem bazowym.

To pozwala konstruować typy, które są identyczne co do struktury, ale niezgodne.

Przykład:

type metry is new Float;

type stopy is new Float;

(32)

Podtypy

Podtyp to typ już istniejący z pewnym ograniczeniem zakresu.

Zakłada się, że jest zgodny z typem bazowym.

Przykład:

subtype SmallInt is Integer range 0..99;

Cytaty

Powiązane dokumenty

Polya w swojej bardzo interesującej książce Jak to rozwiązać (1964) przed­ stawia budowę zadań matematycznych. Każde z nich składa się z: danych, szu­ kanej i warunku. Dane

Podsumowując część analizy wyników dla współczynnika zmiany Z, można stwier- dzić, że (1) na poziomie całej próby uczniowie słabsi w skali współczynnika zmiany Z uzy- skali

CAŁKOWANIE PODSTAWOWYCH TYPÓW FUNKCJI.

Drzewko syntaktyczne dla każdej funkcji powinno zaczynać się od węzła wejściowego, po którym następuje drzewko węzłów reprezentujących działania, które mają być podjęte

Cel lekcji: Zastosowanie zdobytych wiadomości i umiejętności podczas rozwiązywania zadań.. Powtórz podstawowe pojęcia działu

Monika Wrzosek (IM UG) Programowanie obiektowe 145 / 148.. skojarzenie obiektu z metodą jest wykonywane w trakcie działania programu. Sprawdzeniu podlega rzeczywisty typ

Podstawową i w praktyce jedyną wielkością mierzoną podczas weryfikacji parametrów oświetlenia elektrycznego we wnętrzach jest natężenie oświetlenia, które mierzy się za

Takie rozwiązanie Jest wygodne, ale może być niebezpieczne, zwłaszcza jeśli mieszanie typów jest wynikiem błędu programisty..