În programare, avem nevoie tot timpul de reținerea anumitor valori în memoria calculatorului. O variabilă este o zonă de memorie care își poate schimba valoarea pe parcursul execuției programului. Pentru a putea folosi o variabilă, aceasta trebuie mai întâi declarată. Sintaxa declarării unei variabile în C++ este:

Efectul este alocarea unei zone de memorie, unde va fi stocată variabila nume de tipul tip. Alocarea memoriei poate fi statică, auto, dinamică sau registru.

Cea statică este specifică variabilelor globale (cele declarate în afara funcțiilor). Variabilele globale sunt stocate în zona de date a programului, și sunt inițializate automat cu 0.

Variabilele corespunzătoare alocării auto sunt cele locale. Variabilele locale sunt cele declarate într-o funcție (de exemplu main), într-o instrucțiune for… în general într-un block de cod. Acestea sunt stocate în stivă, și nu se știe niciodată ce valoare primesc după declarare (de aceea e bine să le inițializăm noi).

Alocarea dinamică de memorie se face în timpul execuției programului, și aceste variabile sunt stocate în zona numită heap, despre care voi vorbi în alte articole. Exemple:

Variabilele alocate în mod registru sunt stocate într-un registru mașină, pentru a fi accesate mai ușor. Compilatoarele moderne alocă memorie registru chiar fără să specificăm, deoarece detectează singure unde este nevoie. Sintaxa este:

Se pot declara mai multe variabile de același tip printr-o singură instrucțiune:

Variabilele trebuie să poarte un nume pentru a ne putea referi la ele în cadrul expresiilor. Numele unei variabile este un identificator. În C++, identificatorii trebuie să înceapă cu underscore (_) sau cu o literă din alfabetul englez, și să continue cu 0, 1 sau mai multe litere, cifre sau underscore-uri. C++ este case-sensitive, așa că NUMAR, Numar și numar sunt variabile diferite. Identificatorii nu trebuie să coincidă cu keyword-urile standard ale limbajului:

alignas, alignof, and, and_eq, asm, auto, bitand, bitor, bool, break, case, catch, char, class, compl, const, constexpr, const_cast, continue, decltype, default, delete, do, double, dynamic_cast, else, enum, explicit, export, extern, false, float, for, friend, goto, if, inline, int, long, mutable, namespace, new, noexcept, not, not_eq, nullptr, operator, or, or_eq, private, protected, public, register, reinterpret_cast, return, short, signed, sizeof, static, static_assert, static_cast, struct, switch, template, this, thread_local, throw, true, try, typedef, typeid, typename, union, unsigned, using, virtual, void, volatile, wchar_t, while, xor, xor_e

O bună parte dintre ele nici nu sunt folosite în programarea de zi cu zi, așa că nu trebuie reținute pe de rost. Oricum când vom încerca să compilăm programul vom primi o eroare dacă folosim un astfel de identificator greșit. Plus că, CodeBlocks de exemplu, ne colorează cele mai utilizate keyword-uri standard ale limbajului în albastru.

Tipuri fundamentale de date în C++

Grup Tip Mărime Interval de valori
Caractere signed char 1 byte [-27, 27 - 1]
unsigned char 1 byte [0, 28]
Numere întregi signed char 1 byte [-27, 27 - 1]
signed short int 2 bytes [-215, 215 - 1]
signed int 4 bytes [-231, 231 - 1]
signed long int 4 bytes [-231, 231 - 1]
signed long long int 8 bytes [-263, 263 - 1]
Numere naturale unsigned char 1 byte [0, 28 - 1]
unsigned short int 2 bytes [0, 216 - 1]
unsigned int 4 bytes [0, 232 - 1]
unsigned long int 4 bytes [0, 232 - 1]
unsigned long long int 8 bytes [0, 264 - 1]
Numere reale float 4 bytes precizie de 2-3 zecimale
double 8 bytes precizie dublă
long double 10 bytes precizie mai mare decât double
Boolean bool 1 byte true, false
Nul void 0 bytes -
Pointeri decltype(nullptr) variază în funcție de tipul pointer-ului adresa unei variabile

Porțiunile italice sunt opționale în specificarea numelui tipului, însă nu recomand omiterea keyword-ului int, deoarece compilatoarele (foarte) vechi s-ar putea să nu identifice tipul.

Tipul caracter

O variabilă de tip char stochează un caracter, mai exact codul său ASCII. De aceea, tipul caracter este folosit și pentru a stoca numere întregi micuțe. Pentru calculator, un caracter și codul său ASCII sunt același lucru, diferența se vede doar la citire și afișare.

Tipul întreg/natural

Primul bit din reprezentarea unui număr întreg se numește bit de semn, și ia valoarea 0 dacă numărul reprezentat este pozitiv, sau 1 dacă e negativ. Restul biților sunt reprezentarea în baza 2 a numărului respectiv. Într-o variabilă de tip natural (unsigned), nu există bit de semn, deoarece toți biții sunt reprezentarea în baza 2 a numărului dat. Asta permite memorarea unei valori pozitive aproape duble decât permite tipul corespondent cu semn. Puteți afla mai multe despre cum sunt reprezentate numerele întregi în C++ în articolul meu despre Operații pe biți.

Tipul real

O variabilă float/(long) double este reprezentată prin mantisă și exponent. Reprezentarea aceasta este cam greu de înțeles așa că nu o să intru acum în detalii. Când e nevoie să lucrăm cu numere reale, recomand tipul double. Doar dacă trebuie să reținem foarte multe variabile, cu precizie de maxim două zecimale, e OK float, deoarece consumă mai puțină memorie.

Numerele periodice sau iraționale nu pot fi reținute în memoria calculatorului pentru simplul fapt că au o infinitate de zecimale. În schimb, pot fi reținute aproximări ale lor. Există și excepții. De exemplu, matematic, 1,9 = 2, iar 2 poate fi reținut fără probleme în double.

Inițializarea variabilelor

Să inițializăm o variabilă înseamnă să-i atribuim o valoare imediat după ce am declarat-o. Pentru asta folosim operatorul de atribuire (=). Al doilea operand (valoarea pe care o atribuim variabilei) poate fi o constantă, o expresie sau o altă variabilă, deja declarată.

Mai există două moduri prin care putem inițializa o variabilă: punând valoarea între paranteze sau acolade:

Ce înseamnă overflow?

Overflow este o rezultatul unei operații care încearcă să creeze o valoare numerică ce iese din intervalul de valori pe care îl suportă tipul respectiv de date. Rezultatul este reținerea unei valori diferite de cea dorită. De exemplu, instrucțiunea unsigned int a = 4294967296; produce un overflow, deoarece acea valoare depășește cu 1 maximul suportat de unsigned int. Variabila a va stoca de fapt valoarea 0, pentru că atunci când se caută valoarea de după 4294967295, se continuă cu începutul intervalului, unde se găsește 0.

Operatorul sizeof()

sizeof() este un operator (și nu o funcție!) care determină mărimea în bytes a operandului. Acesta poate fi numele unui tip de date sau o variabilă (caz în care parantezele nu mai sunt obligatorii). Exemplu:

decltype() și auto

decltype() este un specificator care arată și el ca o funcție. Acesta determină tipul prin care a fost declarat parametrul. Sintaxa:

decltype poate fi folosit pentru a declara noi variabile. Iată un exemplu:

Keyword-ul auto este folosit tot pentru a declara variabile, dar fără a le specifica explicit tipul. Acesta va fi dedus de compilator, în funcție de valoarea prin care este inițializată (dacă folosim auto este obligatoriu să inițializăm variabila la declarare). Iată câteva exemple:

Cei doi specificatori sunt mult mai puternici de atât, însă nu-i recomand decât în contextul programării generice.

Următorul tutorial de C++ ce merită citit este Constante în C++. Dacă aveți vreo întrebare despre variabile și tipuri de date în C++, vă rog să o adresați în rubrica de comentarii 🙂

Îți place conținutul acestui site?

Dacă vrei să mă susții în întreținerea server-ului și în a scrie mai multe articole de calitate pe acest blog, mă poți ajuta printr-o mică donație. Află aici cum o poți face!