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ść dodatnialowest()— 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 happenZawijanie 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; // infBezpieczne 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.cppSzybkie 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
- Typy całkowitoliczbowe a zmiennoprzecinkowe
- Nagłówek cmath: pow, sqrt, abs, round
- Liczby losowe z nagłówkiem random
- Zakresy liczbowe i przepełnienie