zmienna - to obiekt w programowaniu, który przechowuje różnego rodzaju dane niezbędne do działania programu. Zmienna podczas działania programu może zmieniać swoje wartości (jak wskazuje nazwa). Tworząc zmienną musimy nadać jej nazwę oraz typ, który określa co nasza zmienna będzie przechowywać. Nadając nazwę trzymamy się następujących reguł:
typ zmiennej - tworząc zmienną musimy się zastanowić, jakie będzie jej zastosowanie. Zmienne mogą przechowywać znaki, liczby całkowite, liczby rzeczywiste, ciągi znaków lub wartość logiczną true lub false. W dalszej części dokumentu zostaną zilustrowane podstawowe typy zmiennych, ich rozmiar, zakres i zastosowanie.
Ogólna zasada tworzenia zmiennych jest następująca:
typ_zmiennej nazwa_zmiennej;
np.
int a - zmienna o nazwie "a" mająca typ całkowity int
char b - zmienna o nazwie "b" mająca typ znakowy char.
Prześledźmy przykłady:
int a; //stworzenie zmiennej typu całkowitego o nazwie "a"
int b = 8; //stworzenie zmiennej typu całkowitego o nazwie "b" i nadanie jej wartości 8
int x, y = 80, z, k =7; //stworzenie kilku zmiennych typu całkowitego, nadając niektórym
//zmiennym wartości
Pierwsza grupa to zmienne typu całkowitego. Jak sama nazwa mówi, przechowują tylko liczby całkowite. Różnią się one rozmiarem, czyli zakresem przechowywanych liczb. Im większy rozmiar, tym większe liczby mogą być przechowane.
Typy całkowite
Nazwa | Wielkość (bajty) | Zakres |
---|---|---|
short | 2 | -215÷ 215 - 1, czyli przedział [-32768, 32767] |
int | 4 | -231÷ 231 - 1, czyli przedział [-2147483648, 2147483647] |
long | 4 | -231÷ 231 - 1, czyli przedział [-2147483648, 2147483647] |
long long | 8 | -263÷ 263 - 1, czyli przedział [-9223372036854775808, 9223372036854775807] |
unsigned short | 2 | 0 ÷ 216 - 1, czyli przedział [0, 65535] |
unsigned int | 4 | 0 ÷ 232 - 1, czyli przedział [0, 4294967295] |
unsigned long | 4 | 0 ÷ 232 - 1, czyli przedział [0, 4294967295] |
unsigned long long | 8 | 0 ÷ 264 - 1, czyli przedział [0, 18446744073709551615] |
Warto zauważyć, że po dodaniu słowa kluczowego unsigned (bez znaku), wartości zmiennych stają się nieujemne i podwojony zostaje prawy zakres.
Uwaga!!! Dane w tabeli określają typy zdefiniowane w kompilatorze 32 bitowym Dev C++. W kompilatorach 64 bitowych, zakresy niektórych zmiennych będą większe. |
Patrząc na dane w tabeli, łatwo jest dostosować dany typ do potrzeb programu. Gdy orientujemy się jakich wielkości będziemy używać (jak duże będą liczby w naszym programie), dobieramy optymalny typ.
Typ rzeczywisty - przechowuje liczby zmiennoprzecinkowe. Gdy mamy zamiar w naszym programie wykorzystać ułamki, ten typ będzie najbardziej odpowiedni. Wyróżniamy następujące typy:
Nazwa | Wielkość (bajty) | Zakres |
---|---|---|
float | 4 | pojedyncza precyzja - dokładność 6 - 7 cyfr po przecinku |
double | 8 | podwójna precyzja - dokładność 15 - 16 cyfr po przecinku |
long double | 12 | liczby z ogromną dokładnością - 19 - 20 cyfr po przecinku |
Uwaga!!! Dane w tabeli określają typy zdefiniowane w kompilatorze 32 bitowym Dev C++. W kompilatorach 64 bitowych, zakresy niektórych zmiennych będą większe. |
Typ znakowy - przechowuje znaki, które są kodowane kodem ASCII. Tzn. znak w pamięci nie może być przechowany jako znak, tylko jako pewna liczba. Dlatego każdy znak ma swój odpowiednik liczbowy z zakresu [0, 255], który nazywamy kodem ASCII. I na przykład litera "d" ma wartość 100, "!" = 33, itd.:
Nazwa | Wielkość (bajty) | Zakres |
---|---|---|
char | 1 | -128 ÷ 127 |
unsigned char | 1 | 0 ÷ 255 |
Popatrzmy jeszcze na operację przypisania stosowaną na zmiennych typu znakowego:
char znak;//stworzenie zmiennej znakowej o nazwie "znak"
char litera = 'w'; //stworzenie zmiennej znakowej o nazwie "litera" i przypisanie
//do niej znaku "w". Zauważmy, że znaki wpisujemy w pojedynczym
// apostrofie.
char q = 'q'; // jak wyżej
char p = q; // przypisanie do zmiennej znakowej "q" wartość zmiennej "p", czyli znak "q"
Typ logiczny - przechowuje jedną z dwóch wartości - true (prawda) albo false (fałsz). Wartość logiczna true jest równa 1, natomiast false ma wartość 0.
Nazwa | Wielkość (bajty) | Zakres |
---|---|---|
bool | 1 |
true (1) false (0) |
Dla zmiennych tego typu możemy realizować przypisanie na dwa sposoby, podając wartość true lub fałsz, albo 1 lub 0.
bool a = true; //nadanie wartości true dla zmiennej "a"
bool b = 1; //przypisanie wartości 1 (czyli true) dla zmiennej "b"
int x = 3, y = 11;
bool c = x == y; //zmiennej "c" zostanie nadana wartość false, ponieważ warunek jest fałszywy
// wartość zmiennej "x" nie jest przecież równa wartości zmiennej "y"
bool d = x <= y; //zmiennej "d" zostanie nadana wartość true, ponieważ warunek jest prawdziwy
// wartość zmiennej "x" jest przecież mniejsza od wartości zmiennej "y"
Programowanie w języku C++ opiera się na idei korzystania ze zmiennych lokalnych. Zmienne tego typy "widoczne" są tylko w określonym bloku. Dzięki temu nie ma niebezpieczeństwa omyłkowego przypisania wartości zmiennej, która jest wykorzystywana w innym miejscu. Prześledźmy przykłady:
#include <iostream>
using namespace std;
void funkcja()
{
int a = 3; //zmienna lokalna "widoczna" tylko w funkcji funkcja(), ale nie w main()
}
int main()
{
int a = 4; //zmienna lokalna "widoczna" w całej funkcji main()
return 0;
}
Zmienne lokalne można także tworzyć w mniejszych blokach ograniczonych nawiasami klamrowymi:
#include <iostream>
using namespace std;
int main()
{
int a = 3;
{ //początek widoczności zmiennej "b"
int b = 4; //zmienna lokalna widoczna tylko w bloku ograniczonym klamrami
} //koniec widoczności zmiennej "b"
int b = 5;
if(a < b)
{
int s; //zmienna s jest widoczna tylko w bloku instrukcji if
}
for(int i = 1/*zmienna i widoczna tylko w instrukcji for*/;i < b;i++)
{
int s = i; //zmienna s widoczna tylko w bloku instrukcji for
cout<<i<<" ";
}
return 0;
}
Ważność zmiennych o tych samych nazwach jest nadpisywana zgodnie z następującą zasadą:
#include <iostream>
using namespace std;
int main()
{
int a = 5 /*zmienna "a" jest zmienną lokalną w całej funkcji main()
ale nie jest widoczna w bloku należącym do if*/
, b = 4;
if(b == 4)
{
int a = 4; // zmienna ta jest "widoczna" w bloku if, ale
// nie jest widoczna w podbloku
{ //podblok
int a = 3; //zmienna ta jest widoczna tylko w tym podbloku,
//w tym miejscu tracą ważność wszystkie zmienne lokalne o nazwie "a", które zostały
//stworzone powyżej
cout<<a; //wyświetlenie wartości 3
} //koniec podbloku
cout<<a; //wyświetlenie wartości 4
}
cout<<a; // wyświetlenie wartości 5
return 0;
}
Zmienne globalne widoczne są w każdym "zakątku" programu. Oznacza to, że można z niej korzystać w każdym miejscu programu. Trzeba jedna zwrócić uwagę, że przy tworzeniu tego typu zmiennych, istnieje niebezpieczeństwo przypadkowego nadpisania jej wartości, co może spowodować nieprawidłowe działanie programu. Dlatego zaleca się korzystanie ze zmiennych lokalnych.
Zmienne globalne deklarujemy przed blokiem funkcji main():
#include <iostream>
using namespace std;
int globalna = 3; //zmienna globalna
void f()
{
cout<<globalna; //zmienna globalna
}
int main()
{
cout<<globalna; //zmienna globalna
f(); //wywołanie funkcji f()
cout<<endl;
return 0;
}
Można nadpisywać zmienne globalne, tworząc zmienną lokalną o takiej samej nazwie:
#include <iostream>
using namespace std;
int globalna = 3; //zmienna globalna
void f()
{
int globalna = 5; //nadpisanie zmiennej globalnej i stworzenie lokalnej o takiej samej nazwie
cout<<globalna<<endl; //zmienna lokalna "widoczna" tylko w funkcji f()
}
int main()
{
f();
cout<<globalna; //zmienna globalna
cout<<ndl;
return 0;
}
Rzutowanie typów polega na konwersji jednego typu na drugi. W przypadku konwersji liczby typu rzeczywistego na całkowitą, obetniemy część ułamkową liczby rzeczywistej, w przypadku konwersji char -> int, zamiast znaku będziemy mieli do dyspozycji liczbę (czyli kod ASCII), pod jaką kryje się dany znak itd..
Konwersję typów wykonuje się według dwóch równoważnych zasad:
double a = 3.34;
//sposób pierwszy
int b = (int) a; //rzutowanie zmiennej rzeczywistej na typ całkowity - zmienna "b" przyjmie wartość 3
//zauważmy, że rzutowanie wykonujemy poprzez wpisanie w nawiasie typu na który
//chcemy przekonwertować
//sposób drugi
int c = int (a); //zauważmy, że rzutowanie wykonujemy poprzez wpisanie w nawiasie zmiennej,
//a przed nią typ, na który rzutujemy
char znak = 'q';
cout<<znak<<": "<<(int)znak; //wyświetlenie kodu ASCII znaku q