Jaka jest różnica między „long”, „long long”, „long int” i „long long int” w C ++?

209

Przechodzę z Javy do C ++ i mam kilka pytań na temat longtypu danych. W Javie, aby utrzymać liczbę całkowitą większą niż 2 32 , wystarczy napisać long x;. Jednak w C ++ wydaje się, że longjest to zarówno typ danych, jak i modyfikator.

Wydaje się, że istnieje kilka sposobów użycia long:

long x;
long long x;
long int x;
long long int x;

Ponadto wydaje się, że istnieją takie rzeczy jak:

long double x;

i tak dalej.

Jaka jest różnica między tymi wszystkimi różnymi typami danych i czy wszystkie mają ten sam cel?

1110101001
źródło
2
@ user2612743 - aby być bezpiecznym, zastanów się, jakie są twoje wymagania i użyj odpowiedniego typu. long longmoże być wolniejszy niż long, co może być wolniejszy niż int.
Pete Becker
1
Nie, „żeby być bezpiecznym, używaj długiego” to to samo, co mówiąc: „aby być bezpiecznym, po prostu daj wszystkim jedną ziemską AIDS, więc nie musimy się martwić o bezpieczny seks, wszyscy już to mamy!”. Głupie, nie? Pomyśl o danych i możliwych możliwych wartościach i zastosuj najlepiej dopasowany typ. Pomaga to również kompilatorowi w dokonywaniu dodatkowych optymalizacji bez naruszenia pierwotnego zamiaru kodu, na przykład w przypadku konieczności załadowania dodatkowych bibliotek do obsługi liczb większych niż naturalna szerokość bitów platformy docelowej.
CM
Długie używanie z listami win32 i tym podobnymi nie spowoduje spustoszenia w pamięci i innych zmiennych - nawet jeśli limity nie zostaną przekroczone. Nawet przy nieszkodliwych ostrzeżeniach C4244 nie jest łatwo wykryć.
Laurie Stearn

Odpowiedzi:

182

longi long intsą identyczne. Podobnie jak long longi long long int. W obu przypadkach intopcja jest opcjonalna.

Jeśli chodzi o różnicę między tymi dwoma zestawami, standard C ++ nakazuje minimalne zakresy dla każdego, a long longto co najmniej tak szeroki jak long.

Kontrolujące części standardu (C ++ 11, ale to już istnieje od dłuższego czasu) to, na przykład 3.9.1 Fundamental types, sekcja 2 (późniejsza sekcja podaje podobne reguły dla niepodpisanych typów całek):

Istnieje pięć standardowych typów liczb całkowitych ze znakiem: znak, char, short int, int, long int i long long int. Na tej liście każdy typ zapewnia co najmniej tyle miejsca, ile poprzedza go na liście.

Jest też tabela 9, w 7.1.6.2 Simple type specifiersktórej pokazano „odwzorowania” specyfikatorów na rzeczywiste typy (pokazujące, że intopcja jest opcjonalna), której sekcja pokazano poniżej:

Specifier(s)         Type
-------------    -------------
long long int    long long int
long long        long long int
long int         long int
long             long int

Zwróć uwagę na różnicę między specyfikatorem a typem. Specyfikator to sposób, w jaki informujesz kompilator, jaki jest typ, ale możesz użyć różnych specyfikatorów, aby uzyskać ten sam typ.

Dlatego sam longw sobie nie jest typem ani modyfikatorem, jak stawia twoje pytanie, jest po prostu specyfikatorem long inttypu. To samo dotyczy long longbycia specyfikatorem long long inttypu.

Chociaż sam standard C ++ nie określa minimalnych zakresów typów całkowych, cytuje C99 1.2 Normative references, jak to ma zastosowanie. Dlatego obowiązują minimalne zakresy określone w C99 5.2.4.2.1 Sizes of integer types <limits.h>.


Z punktu widzenia long doubletego jest to właściwie liczba zmiennoprzecinkowa, a nie liczba całkowita. Podobnie jak w przypadku typów całkowych, wymagana jest co najmniej tyle samo precyzji co a, doublea także zapewnienie zestawu wartości nad tym typem (co najmniej te wartości, niekoniecznie więcej wartości).

paxdiablo
źródło
4
to samo z unsignediunsigned int
Kal
2
Jestem prawie pewien, że longma co najmniej 32 bity (2 ^ 31-1 po każdej stronie zera) i long longma co najmniej 64 (2 ^ 63-1 po każdej stronie).
Chris
2
I long doublema zagwarantowany przynajmniej zasięg double, ale może być taki sam. To zależy od komputera. Niektóre FPU mają rozszerzoną precyzję; chipy x87 miały 32-bitową pojedynczą precyzję, 64-bitową podwójną precyzję i 80-bitową rozszerzoną precyzję.
Eric Jablow
Jeśli chodzi o wymagania dotyczące zakresu, standard C ++ 11 odwołuje się do standardu C11, który ma rzeczywiste zakresy.
Chris
Część „int” po prostu odróżnia typ liczby całkowitej od liczby zmiennoprzecinkowej, znaku lub innego typu niecałkowitego. W wielu przypadkach może to wywnioskować kompilator, więc można je usunąć - dlatego na przykład „niepodpisany” jest taki sam jak „bez znaku int”. Część „int” jest po prostu zakładana, chyba że programista określi coś innego, na przykład „char” lub „double”. Co do rzeczywistych rozmiarów używanych ... w zależności od standardu, który czytasz, każdy rozmiar może mieć minimalną liczbę bitów, ale wszystkie są zdefiniowane tak, że każdy jest co najmniej tak duży, jak poprzedni typ.
CM
17

longjest równoważne long int, tak jak shortjest równoważne z short int. A long intjest znakiem typu całkowego, który ma co najmniej 32 bity, podczas gdy a long longlub long long intjest znakiem typu całkowego, który ma co najmniej 64 bity.

To niekoniecznie oznacza, że ​​a long longjest szerszy niż a long. Wiele platform / ABI korzysta z LP64modelu - gdzie long(i wskaźniki) mają szerokość 64 bitów. Win64 używa LLP64, gdzie longwciąż jest 32 bitów, a long long(i wskaźniki) mają szerokość 64 bitów.

Jest to podsumowanie dobra 64-bitowych modeli danych tutaj .

long doublenie gwarantuje wiele innych niż będzie co najmniej tak szeroki jak double.

Brett Hale
źródło
7

To wydaje się mylące, ponieważ sam bierzesz longjako typ danych.

longjest niczym innym, jak tylko skrótem, long intgdy używasz go sam.

longjest modyfikatorem, możesz go używać doublerównież jakolong double .

long== long int.

Oba zajmują 4 bajty.

Siraj Alam
źródło
Długie zajęcie 4 bajtów jest ważne tylko na Win64, zależy od platformy
Prodigle
1
Tak, oczywiście ... nie tylko długi ... int zajmuje 4 bajty, a 2 bajty zależą od platformy, bez wątpienia.
Siraj Alam,
3

Historycznie, we wczesnych czasach C, kiedy procesory miały 8 lub 16 bitów długości słowa, intbyły identyczne z dzisiejszymi short(16 bitów). W pewnym sensie, int jest bardziej abstrakcyjny typ danych niż char, short, longlub long long, jak nie można mieć pewności co do bitwidth.

Podczas definiowania int n;możesz to przetłumaczyć za pomocą „daj mi najlepszy kompromis w zakresie przepustowości i prędkości na tym komputerze dla n”. Być może w przyszłości powinieneś spodziewać się, że kompilatory intbędą miały wersję 64-bitową. Więc jeśli chcesz, aby twoja zmienna miała 32 bity i więcej, lepiej użyj jawnego longjako typu danych.

[Edycja: #include <stdint.h>wydaje się być właściwym sposobem na zapewnienie przepływności przy użyciu typów int ## _ t, chociaż nie jest to jeszcze częścią standardu.]

Thomiel
źródło
2
Ta ostatnia część, używając „długiego”, aby uzyskać 32 bity, gdy int ma 64 bity, jest niepoprawna. Jeśli int jest 64-bitowy, to również długi będzie wynosić co najmniej 64-bitowy. Długa jest gwarantowana co najmniej tak duża jak int, chociaż może być większa, ale nigdy mniejsza. Większość kompilatorów ma różne metody, które pozwalają na bardziej precyzyjne programowanie, takie jak (nieprzenośny) typ __int32, który ma dokładnie 32 bity i tak dalej.
CM
1
Jak zdefiniowano w standardzie C, longgwarantowana jest wartość co najmniej 32 bitów. (Normy mogą ulec zmianie.) Obecny projekt C ++ 14 mówi tylko: @CM „Zwykłe inty mają naturalny rozmiar sugerowany przez architekturę środowiska wykonawczego, inne podpisane typy liczb całkowitych mają na celu zaspokojenie specjalnych potrzeb” (sekcja 3.9.1 ). Nie znalazłem w nim ani słowa o relacjach długości różnych int. __int32 nie jest tak naprawdę częścią standardu, ale od C ++ 11 dostępne są typy typef, takie jak int_fast32_t lub int_least32_t, aby uzyskać dokładnie to, czego chcesz.
thomiel,
Powiedziałbym, że w dwudziestowiecznych implementacjach mikrokomputerów ogólnego przeznaczenia, reprogramowalnych, charmiał prawie jednogłośnie 8 bitów, short16 i long32; intmoże mieć 16 lub 32. Uwaga na niektórych platformach (zwłaszcza 68000) zarówno 16-bitowe, jak i 32-bitowe intbyły dość powszechne, a niektóre kompilatory miały opcje do obsługi. Kod, który musiał być przenośny, miał więc być używany shortlub longpreferowany int.
supercat
0

Podczas gdy w Javie a longma zawsze 64 bity, w C ++ zależy to od architektury komputera i systemu operacyjnego . Na przykład, a longto 64 bity w systemie Linux i 32 bity w systemie Windows (zostało to zrobione, aby zachować zgodność wsteczną, umożliwiając 32-bitowym programom kompilację w 64-bitowym systemie Windows bez żadnych zmian).

Uważany jest za dobry styl C ++, którego należy unikać, short int long ... a zamiast tego należy użyć:

std::int8_t   # exactly  8 bits
std::int16_t  # exactly 16 bits
std::int32_t  # exactly 32 bits
std::int64_t  # exactly 64 bits

std::size_t   # can hold all possible object sizes, used for indexing

Te ( int*_t) można wykorzystać po dołączeniu <cstdint>nagłówka. size_tjest w <stdlib.h>.

xjcl
źródło