Fiecare variabilă din C++ are un tip, iar tipul decide trei lucruri: ce valori poate reține variabila, câtă memorie ocupă și cum se comportă în calcule. La BAC informatică nu ți se cere să știi pe de rost numărul de octeți al fiecărui tip, dar trebuie să alegi corect între int și long long, să știi când o împărțire dă rezultat real și cum se comportă char în expresii.

Tipurile întregi: int și long long

Pe compilatoarele folosite în mod obișnuit (GCC, Code::Blocks, Visual Studio), valorile sunt:

TipMemorieInterval aproximativ
int4 octețide la -2 147 483 648 la 2 147 483 647 (cam ±2·109)
unsigned int4 octețide la 0 la 4 294 967 295
long long8 octețicam ±9,2·1018
short2 octețide la -32 768 la 32 767

Regula practică pentru citirea enunțului: un număr cu cel mult 9 cifre încape sigur în int, pentru că 999 999 999 este mai mic decât 2 147 483 647. Un număr cu 10 cifre s-ar putea să nu încapă, iar unul cu cel mult 18 cifre cere long long.

Atenție și la rezultatele calculelor, nu doar la datele de intrare. Dacă citești până la un milion de numere de cel mult 9 cifre și le aduni, suma poate ajunge la aproximativ 1015, deci variabila sumă trebuie să fie long long, chiar dacă fiecare număr încape în int.

Depășirea (overflow): greșeala care nu dă eroare

Când un calcul cu int depășește intervalul, programul nu se oprește și nu afișează niciun mesaj: pur și simplu obții o valoare greșită, de cele mai multe ori negativă. Exemplul clasic este factorialul: 12! = 479 001 600 încape în int, dar 13! = 6 227 020 800 nu mai încape. În long long încape până la 20! = 2 432 902 008 176 640 000; 21! depășește și acest tip.

O capcană mai subtilă:

int x = 100000;
long long p = x * x;        // GREȘIT: x * x se calculează în int și depășește
long long q = 1LL * x * x;  // CORECT: 1LL * x este long long, deci produsul la fel

Tipul variabilei din stânga nu contează pentru calculul din dreapta. Expresia x * x se evaluează cu tipul operanzilor (ambii int), iar abia rezultatul deja stricat se copiază în p. De aceea, ori declari x direct long long, ori forțezi conversia ca în a doua linie.

Tipurile reale: double și float

double ocupă 8 octeți și reține aproximativ 15–16 cifre semnificative; float ocupă 4 octeți și are doar în jur de 7 cifre semnificative. La BAC folosește double ori de câte ori ai nevoie de zecimale (medii, rapoarte, rădăcini).

Numerele reale sunt reținute aproximativ. De aceea 0.1 + 0.2 == 0.3 are valoarea false în C++. Când compari valori reale rezultate din calcule, evită ==; dacă poți, lucrează cu întregi. De exemplu, în loc să verifici sqrt(n) == (int)sqrt(n) pentru pătrat perfect, calculează r = sqrt(n) ca întreg și verifică r * r == n.

Tipul char: un caracter este, de fapt, un număr

O variabilă char ocupă un octet și reține codul ASCII al unui caracter. Câteva coduri utile: '0' are codul 48, 'A' are 65, 'a' are 97, spațiul are 32. Literele mari și cele mici sunt la distanță de 32: 'a' - 'A' == 32.

Pentru că un char este un număr, poți face calcule cu el:

Diferența dintre afișări contează la grile: cout << 'a' + 1; afișează 98, pentru că rezultatul expresiei este de tip int, pe când cout << (char)('a' + 1); afișează b.

Tipul bool

bool are doar două valori: true și false. La afișare cu cout apar ca 1 și 0. Orice valoare numerică nenulă convertită la bool devine true, iar 0 devine false. Asta explică de ce if (n % 2) este echivalent cu if (n % 2 != 0).

Tipul bool este potrivit pentru funcțiile care răspund cu „da” sau „nu”, de exemplu bool prim(int n), și pentru vectorii de marcaje (ciurul lui Eratostene, vectori de apariții), unde ocupă un singur octet pe element.

Conversiile automate pe care le face compilatorul

Când într-o expresie apar tipuri diferite, compilatorul convertește operanzii la tipul „mai larg”, după câteva reguli simple:

Iată un program scurt pe care îl poți rula ca să vezi toate aceste efecte:

#include <iostream>
using namespace std;

int main()
{
    int a = 7, b = 2;
    double r = 3.99;
    char c = 'a';
    cout << a / b << "\n";          // 3
    cout << a / 2.0 << "\n";        // 3.5
    cout << (int)r << "\n";         // 3
    cout << c + 1 << "\n";          // 98
    cout << (char)(c + 1) << "\n";  // b
    cout << (5 > 3) << "\n";        // 1
    long long f = 1;
    for (int i = 1; i <= 20; i++)
        f = f * i;
    cout << f << "\n";              // 2432902008176640000
    return 0;
}
La BAC: când declari variabilele la Subiectul III, uită-te la restricțiile din enunț („numere naturale cu cel mult 9 cifre”, „cel mult 106 numere”) și întreabă-te care este cea mai mare valoare pe care o poate atinge fiecare variabilă, inclusiv sumele și produsele. Un long long pus din prudență nu costă puncte; o depășire, da.

Cum alegi tipul, pe scurt

  1. Numere naturale sau întregi de cel mult 9 cifre: int.
  2. Sume mari, produse, factoriale, numere de 10–18 cifre: long long.
  3. Medii, rapoarte, rezultate cu zecimale: double.
  4. Caractere și prelucrări de text: char (și tablouri de char pentru șiruri).
  5. Rezultate de tip da/nu și marcaje: bool.

De reținut