Ce face signed, unsigned, short, long
short și long schimbă mărimea unui întreg: short are cel puțin 16 biți, long cel puțin 32, long long cel puțin 64. Mărimea exactă depinde de sistem: long are 8 octeți pe Linux și macOS pe 64 de biți, dar doar 4 pe Windows. Dacă ai nevoie de o mărime exactă, folosește std::int64_t și tipurile din <cstdint>.
unsigned face ca tipul să nu aibă semn: nu poate ține valori negative, dar poate ține valori pozitive de două ori mai mari. signed este implicit pentru int, short și long, deci se scrie de obicei doar la signed char.
Calculele cu unsigned nu depășesc niciodată limita: rezultatul „se întoarce” (0 – 1 devine valoarea maximă). Comportamentul este bine definit, dar sursă frecventă de greșeli.
Exemple
Exemplul 1: Mărimile tipurilor întregi
Rezultatul este de pe macOS pe 64 de biți (Apple M). Pe Windows, long ar avea 4 octeți.
#include <print>
int main() {
std::println("short: {} octeți", sizeof(short));
std::println("int: {} octeți", sizeof(int));
std::println("long: {} octeți", sizeof(long));
std::println("long long: {} octeți", sizeof(long long));
std::println("unsigned int: {} octeți", sizeof(unsigned int));
}
Rezultat
short: 2 octeți
int: 4 octeți
long: 8 octeți
long long: 8 octeți
unsigned int: 4 octeți
Exemplul 2: Limitele cu și fără semn
#include <limits>
#include <print>
int main() {
std::println("short: {} ... {}", std::numeric_limits<short>::min(), std::numeric_limits<short>::max());
std::println("unsigned short: {} ... {}", std::numeric_limits<unsigned short>::min(), std::numeric_limits<unsigned short>::max());
std::println("long long: {} ... {}", std::numeric_limits<long long>::min(), std::numeric_limits<long long>::max());
std::println("unsigned int: {} ... {}", std::numeric_limits<unsigned int>::min(), std::numeric_limits<unsigned int>::max());
}
Rezultat
short: -32768 ... 32767
unsigned short: 0 ... 65535
long long: -9223372036854775808 ... 9223372036854775807
unsigned int: 0 ... 4294967295
Exemplul 3: Întoarcerea valorilor fără semn
Scăzând 1 din 0 într-un unsigned int, rezultatul devine cea mai mare valoare posibilă. Adunând 1 la maxim, revine la 0.
#include <print>
int main() {
unsigned int stoc = 0;
stoc = stoc - 1;
std::println("0 - 1 = {}", stoc);
stoc = stoc + 1;
std::println("înapoi la {}", stoc);
long long populatie_lume = 8'100'000'000;
std::println("Populația lumii: {}", populatie_lume);
}
Rezultat
0 - 1 = 4294967295
înapoi la 0
Populația lumii: 8100000000
Greșeli frecvente
- Compari un număr cu semn cu unul fără semn:
-1 < 0uestefalse, pentru că -1 este transformat într-ununsigneduriaș. Compilatorul avertizează (-Wsign-compare); foloseștestd::cmp_lesssau același tip în ambele părți. - Scrii o buclă descrescătoare cu
unsigned:for (unsigned i = n - 1; i >= 0; --i). Condiția este mereu adevărată (ununsignednu e niciodată negativ), deci bucla nu se oprește. - Presupui că
longare 8 octeți. Pe Windows are 4, deci programul care merge pe Linux dă rezultate greșite. Pentru 64 de biți garantat foloseștelong longsaustd::int64_t.
Comenzi înrudite
int: Tipul de bază pentru numere întregi (fără zecimale), de obicei pe 4 octeți, cu valori între aproximativ -2,1 și 2,1 miliarde.char: Tipul pentru un singur caracter (un octet); în spate este un număr mic, codul caracterului.sizeof: Dă numărul de octeți ocupați în memorie de un tip sau de o variabilă; se calculează la compilare.double, float: Tipuri pentru numere reale (cu zecimale): double are aproximativ 15-16 cifre exacte, float doar 6-7.std::numeric_limits: Dă proprietățile unui tip numeric: valoarea maximă și minimă, precizia, dacă are semn, infinitul.std::size_t: Tip întreg fără semn pentru mărimi și indici: îl returnează sizeof și metodele size() ale containerelor.std::int32_t: Tipuri întregi cu mărime exactă: int32_t are mereu 32 de biți, uint8_t 8 biți fără semn etc.