0Pricing
C++ Academy · Lekcja

Zakresy liczbowe i przepełnienie

Odczytuj std::numeric_limits i poznaj zasady przepełnienia typów ze znakiem i bez znaku

Zakresy liczbowe i przepełnienie to bezpłatna lekcja C++ Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C++ Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C++ Academy zawiera 4 lekcji w sumie.

Dlaczego zakresy mają znaczenie

Każdy typ liczbowy ma maksymalną i minimalną reprezentowalną wartość. Ich przekroczenie może po cichu prowadzić do nieprawidłowych wyników lub niezdefiniowanego zachowania.

std::numeric_limits

Zakresy dowolnego typu liczbowego można sprawdzić za pomocą nagłówka <limits>. Są to stałe znane w czasie kompilacji, więc nie powodują żadnego kosztu w czasie działania programu.

#include <limits>
std::cout << std::numeric_limits<int>::max() << "\n";
std::cout << std::numeric_limits<int>::min() << "\n";
std::cout << std::numeric_limits<double>::epsilon();

Najczęściej używane zapytania

Najbardziej przydatne składowe:

  • max() — największa wartość
  • min() — najmniejsza wartość dodatnia
  • lowest() — najbardziej ujemna wartość
  • epsilon() — najmniejsza znacząca różnica (dla liczb zmiennoprzecinkowych)
  • digits10 — gwarantowana liczba cyfr dziesiętnych

Przepełnienie liczb całkowitych ze znakiem

Przepełnienie liczby całkowitej ze znakiem oznacza niezdefiniowane zachowanie. Kompilator może założyć, że nigdy do niego nie dojdzie, co prowadzi do zaskakujących optymalizacji.

int x = std::numeric_limits<int>::max();
x += 1;   // UB — anything can happen

Zawijanie liczb całkowitych bez znaku

Przepełnienie liczby całkowitej bez znaku jest zdefiniowane — wartości zawijają się modulo 2^N. Czasami jest to przydatne, ale często prowadzi do trudnych do wykrycia błędów.

unsigned int u = 0;
u -= 1;   // wraps to 4,294,967,295 (UINT_MAX)

Przepełnienie i niedomiar liczb zmiennoprzecinkowych

W przypadku przepełnienia liczby zmiennoprzecinkowe przyjmują wartość inf, zamiast powodować awarię. Niedomiar prowadzi do liczb podnormalnych albo do wartości 0.

double x = 1e308;
x *= 100;
std::cout << x;  // inf

Bezpieczne wykrywanie przepełnienia

W przypadku liczb całkowitych ze znakiem sprawdź wynik przed wykonaniem operacji. Kompilatory udostępniają wbudowane funkcje do kontrolowanych operacji arytmetycznych, takie jak __builtin_add_overflow w GCC i Clang.

if (a > std::numeric_limits<int>::max() - b) {
    // overflow would happen
}
int sum = a + b;

C++20 std::ssize i std::cmp_less

W C++20 dodano w nagłówku <utility> bezpieczne funkcje pomocnicze do porównywania liczb całkowitych: std::cmp_equal, cmp_less, cmp_greater. Prawidłowo obsługują mieszanie typów ze znakiem i bez znaku.

Niejawne konwersje bywają zdradliwe

Połączenie typów ze znakiem i bez znaku w porównaniu po cichu konwertuje operand ze znakiem na typ bez znaku — to częste źródło trudnych do wykrycia błędów.

int a = -1;
unsigned int b = 1;
if (a < b) std::cout << "yes";
else       std::cout << "no";   // prints "no"!

Sprawdzanie w czasie kompilacji

Używaj static_assert, aby wymuszać założenia dotyczące rozmiaru podczas pisania przenośnego kodu.

static_assert(sizeof(int) >= 4, "Need at least 32-bit int");

Sanitizery pomagają podczas testów

Kompiluj z opcją -fsanitize=undefined, aby podczas testów wykrywać przepełnienia liczb całkowitych ze znakiem w czasie działania programu.

g++ -fsanitize=undefined -O1 main.cpp

Szybkie sprawdzenie

Co dzieje się w C++, gdy dodawanie liczb całkowitych ze znakiem powoduje przepełnienie?

Podsumowanie

Używaj std::numeric_limits do sprawdzania granic typów. Przepełnienie liczb ze znakiem jest niezdefiniowane, a liczby bez znaku zawijają się. Mieszanie typów ze znakiem i bez znaku może prowadzić do problemów. Sanitizery i bezpieczne porównania z C++20 pomagają chronić kod.

Często zadawane pytania

Czy lekcja „Zakresy liczbowe i przepełnienie” jest bezpłatna?

Tak — pełny tekst „Zakresy liczbowe i przepełnienie” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C++ Academy, przejdź na CoddyKit PRO. Kurs C++ Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Zakresy liczbowe i przepełnienie”?

Odczytuj std::numeric_limits i poznaj zasady przepełnienia typów ze znakiem i bez znaku Ćwiczysz C++ Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C++ Academy?

Nie wymagamy żadnego doświadczenia. C++ Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Zakresy liczbowe i przepełnienie”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C++ Academy?

Tak. Każda lekcja C++ Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Typy całkowitoliczbowe a zmiennoprzecinkowe
  2. Nagłówek cmath: pow, sqrt, abs, round
  3. Liczby losowe z nagłówkiem random
  4. Zakresy liczbowe i przepełnienie
← Powrót do C++ Academy