Programowanie i algorytmy

Zmienne w C++

 powrót

Spis treści

Podstawowe pojęcia

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ł:

  • zmienna jest jednym ciągiem znaków bez spacji np. nazwa_zmiennej - dobrze, nazwa zmiennej - źle
  • nie zaczynamy nazwy od cyfry np. 12zmienna - źle, zmienna12 - dobrze
  • nie używamy polskich liter takich jak ą, ę itp.
  • nazwa zmiennej powinna kojarzyć się z przeznaczeniem tej zmiennej np. tablica_ciagu - dobrze
  • nazwa nie może być słowem kluczowym języka programowania np. auto - źle

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.

Inicjacja zmiennych

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
 

Typy zmiennych

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:

 

Typy rzeczywiste
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.:

 

Typ znakowy
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.

 

Typ logiczny
Nazwa Wielkość (bajty) Wartości
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"
 

Zmienne lokalne i zmienne globalne

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:

 

Przykład 1
#include <cstdlib>
#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()
 
system("pause");
return 0;
 
}
 

 

Zmienne lokalne można także tworzyć w mniejszych blokach ograniczonych nawiasami klamrowymi:

 

Przykład 2
#include <cstdlib>
#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"
 
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<<" ";
 
}
 
system("pause");
return 0;
}
 

 

Ważność zmiennych o tych samych nazwach jest nadpisywana zgodnie z następującą zasadą:

 

Przykład 3
#include <cstdlib>
#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
 
system("PAUSE");
return EXIT_SUCCESS;
}
 

 

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():

 

Przykład 1
#include <cstdlib>
#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;
 
system("pause");
return 0;
}
 

 

Można nadpisywać zmienne globalne, tworząc zmienną lokalną o takiej samej nazwie:

Przykład 2
#include <cstdlib>
#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;
 
system("pause");
return 0;
}
 

 

Rzutowanie typów

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:

Przykład 1
float 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