Szukam szczegółowych informacji dotyczących wielkości podstawowych typów C ++. Wiem, że zależy to od architektury (16 bitów, 32 bity, 64 bity) i kompilatora.
Ale czy są jakieś standardy dla C ++?
Korzystam z programu Visual Studio 2008 w architekturze 32-bitowej. Oto co otrzymuję:
char : 1 byte
short : 2 bytes
int : 4 bytes
long : 4 bytes
float : 4 bytes
double: 8 bytes
Starałem się znaleźć bez większych sukcesów, wiarygodne informacje określające rozmiary char
, short
, int
, long
, double
, float
(i inne rodzaje I nie myśleć) w różnych architektur i kompilatory.
int16_t
,int32_t
iint64_t
(potrzebneiostream
to za to jeśli dobrze pamiętam). Co jest miłego w tym, że int64_t nie powinien mieć problemów w systemie 32-bitowym (wpłynie to jednak na wydajność).<cstdint>
, a nie<iostream>
.Odpowiedzi:
Standard C ++ nie określa wielkości typów całek w bajtach, ale określa minimalne zakresy, które muszą być w stanie pomieścić. Możesz określić minimalny rozmiar w bitach z wymaganego zakresu. Na podstawie tego można wywnioskować minimalny rozmiar w bajtach oraz wartość
CHAR_BIT
makra, która określa liczbę bitów w bajcie . Na wszystkich mało znanych platformach jest to 8 i nie może być mniejsza niż 8. To dlatego, że musi być wystarczająco duża, aby pomieścić „ośmiobitowe jednostki kodu w formie kodowania Unicode UTF-8”.Jednym dodatkowym ograniczeniem
char
jest to, że jego rozmiar wynosi zawsze 1 bajt lubCHAR_BIT
bit (stąd nazwa). Jest to wyraźnie określone w normie.Standard C jest odniesieniem normatywnym do standardu C ++, więc nawet jeśli nie określa on wyraźnie tych wymagań, C ++ wymaga minimalnych zakresów wymaganych przez standard C (strona 22), które są takie same jak w zakresach typów danych na MSDN :
signed char
: Od -127 do 127 (uwaga, nie od -128 do 127; dotyczy to komplementów 1 i platform znak-i-wielkości)unsigned char
: Od 0 do 255char
: ten sam zakres cosigned char
lubunsigned char
, zdefiniowany w implementacjisigned short
: Od -32767 do 32767unsigned short
: Od 0 do 65535signed int
: Od -32767 do 32767unsigned int
: Od 0 do 65535signed long
: -2147483647 do 2147483647unsigned long
: Od 0 do 4294967295signed long long
: -9223372036854775807 do 9223372036854775807unsigned long long
: Od 0 do 18446744073709551615Implementacja C ++ (lub C) może definiować rozmiar typu w bajtach
sizeof(type)
do dowolnej wartości, o ilesizeof(type) * CHAR_BIT
ocenia na liczbę bitów wystarczająco wysoką, aby zawierać wymagane zakresy, orazsizeof(int) <= sizeof(long)
.).Podsumowując, gwarantujemy, że:
char
,signed char
iunsigned char
mają co najmniej 8 bitówsigned short
,unsigned short
,signed int
, Aunsigned int
co najmniej 16 bitówsigned long
iunsigned long
mają co najmniej 32 bitysigned long long
iunsigned long long
mają co najmniej 64 bityNie udziela się gwarancji co do wielkości
float
lubdouble
z wyjątkiem, żedouble
zapewnia ona co najmniej tyle precyzji, cofloat
.Rzeczywiste zakresy specyficzne dla implementacji można znaleźć w
<limits.h>
nagłówku w C lub<climits>
w C ++ (lub nawet lepiej, w szabloniestd::numeric_limits
w<limits>
nagłówku).Na przykład w ten sposób znajdziesz maksymalny zasięg dla
int
:DO:
C ++ :
źródło
char
”, a nie zwykłe znaczenie.W przypadku systemów 32-bitowych standardem de facto jest ILP32 - to znaczy
int
,long
a wskaźnik to 32-bitowe wielkości.W systemach 64-bitowych podstawowym uniksowym standardem „de facto” jest LP64 -
long
a wskaźnik jest 64-bitowy (aleint
32-bitowy). Standardowe 64-bitowy Windows jest LLP64 -long long
i wskaźnik są 64-bitowe (alelong
iint
to zarówno 32-bit).Kiedyś niektóre systemy uniksowe korzystały z organizacji ILP64.
Żadna z tych de facto norm nie jest uregulowana normą C (ISO / IEC 9899: 1999), ale wszystkie są przez nią dozwolone.
I z definicji
sizeof(char)
jest to1
pomimo testu w skrypcie konfiguracyjnym Perla.Zauważ, że nie było maszyny (Crays), gdzie
CHAR_BIT
był znacznie większy niż 8. To oznaczało, IIRC, żesizeof(int)
był również 1, ponieważ zarównochar
iint
były 32-bitowe.źródło
[u]int32_t
lub podobnej, jeśli chcesz użyć wersji 64-bitowej[u]int64_t
... jeśli nie masz dla nich nagłówka, pobierz go lub zrób, najlepiej z wyborem czasu kompilacji takie typy lub twierdzenia statyczne w celu weryfikacji rozmiaru. pubs.opengroup.org/onlinepubs/009695299/basedefs/stdint.h.html Jeśli dokładne rozmiary nie są tak ważne i zależy Ci tylko na ich wielkości, to twoja rada dotyczy popularnych współczesnych platform PC / serwerów.int get_char(FILE *fp, char *c)
która zwraca EOF lub 0 i ustawia*c
.uint32_t x=1,y=2;
pod uwagę, że wartośćx-y
musi wynosić 4294967295 na platformach, na których „int” wynosi 32 bity lub mniej, oraz -1 na platformach, na których „int” ma 33 bity lub więcej. Ponadto wymagax*y
oceny, która musi być oszacowana przy użyciu arytmetyki modułowej dla wszystkich wartości xiy, jeżeli „int” wynosi 32 bity lub mniej, oraz konwencjonalnej arytmetyki, jeśli 65 bitów lub więcej, ale nie nakłada żadnych wymagań na to, co może się stać z dużymi wartościami z xiy, jeżeli „int” ma od 33 do 64 bitów.W praktyce nie ma czegoś takiego. Często można oczekiwać,
std::size_t
że w obecnej architekturze będzie reprezentował rozmiar całkowitą bez znaku dla rodzimej liczby całkowitej. tj. 16-bitowy, 32-bitowy lub 64-bitowy, ale nie zawsze tak jest, jak wskazano w komentarzach do tej odpowiedzi.Jeśli chodzi o wszystkie inne typy wbudowane, tak naprawdę zależy to od kompilatora. Oto dwa fragmenty zaczerpnięte z aktualnej wersji roboczej najnowszego standardu C ++:
Jeśli chcesz, możesz statycznie (czas kompilacji) potwierdzić rozmiar tych podstawowych typów. Ostrzeże ludzi, aby pomyśleli o przeniesieniu kodu, jeśli zmieni się rozmiar założeń.
źródło
Jest standard.
Wymaga tego standard C90
Wymaga tego standard C99
Oto specyfikacja C99 . Strona 22 zawiera informacje o rozmiarach różnych typów całek.
Oto rozmiary typu int (bity) dla platform Windows:
Jeśli martwisz się przenośnością lub chcesz, aby nazwa typu odzwierciedlała rozmiar, możesz spojrzeć na nagłówek
<inttypes.h>
, w którym dostępne są następujące makra:int8_t
ma gwarantowane 8 bitów iint16_t
16 bitów itp.źródło
sizeof(long) < sizeof(long long)
a nie symetrycznysizeof(long) <= sizeof(long long)
?Jeśli potrzebujesz typów o ustalonym rozmiarze, użyj typów takich jak uint32_t (liczba całkowita 32 bez znaku) zdefiniowanych w stdint.h . Są one określone w C99 .
źródło
CHAR_BIT == 16
na przykład nie będzie miałaint8_t
. Każda platforma nieużywająca uzupełnienia dwóch nie będzie miała żadnego z nich (ponieważ standard wymaga uzupełnienia dwóch).Zaktualizowano: C ++ 11 oficjalnie wprowadził typy z TR1 do standardu:
I typy „wielkości” z
<cstdint>
Plus dostajesz:
Te typy reprezentują najmniejsze typy liczb całkowitych z co najmniej określoną liczbą bitów. Podobnie istnieją „najszybsze” typy liczb całkowitych z co najmniej określoną liczbą bitów:
To, co „szybko” znaczy, zależy od wdrożenia. Nie musi być najszybszy do wszystkich celów.
źródło
Standard C ++ mówi tak:
3.9.1, ust. 2:
Wniosek: zależy od architektury, nad którą pracujesz. Wszelkie inne założenia są fałszywe.
źródło
Nie, nie ma standardu dla rozmiarów typów. Standard wymaga jedynie, aby:
Najlepszą rzeczą, jaką możesz zrobić, jeśli chcesz mieć zmienne o stałych rozmiarach, jest użycie takich makr:
Następnie możesz użyć WORD do zdefiniowania zmiennych. To nie tak, że to lubię, ale jest to najbardziej przenośny sposób.
źródło
#include <boost/cstdint.hpp>
Możemy zdefiniować synonim tego typu, abyśmy mogli stworzyć własny „standard”.
Na maszynie, w której sizeof (int) == 4, możemy zdefiniować:
Kiedy więc przeniesiemy kod na inną maszynę, gdzie faktycznie długość długiej int wynosi 4, możemy po prostu przedefiniować pojedyncze wystąpienie int.
źródło
<stdint.h>
(C99 i późniejsze, i którykolwiek standard C ++ przyjął wersję C99 biblioteki C).W przypadku liczb zmiennoprzecinkowych istnieje standard (IEEE754) : liczby zmiennoprzecinkowe są 32-bitowe, a liczby podwójne to 64. Jest to standard sprzętowy, a nie standard C ++, więc kompilatory mogą teoretycznie definiować zmiennoprzecinkowe i podwójne do innych rozmiarów, ale w praktyce I ' nigdy nie widziałem architektury, która używałaby czegoś innego.
źródło
double
ma taki sam rozmiar jakfloat
(iint
taki sam, jakchar
oba są 16-bitowe). Ale mają 64-bitlong double
.Istnieje norma, która jest określona w różnych dokumentach dotyczących norm (ISO, ANSI i tak dalej).
Wikipedia ma świetną stronę wyjaśniającą różne typy i maksymalną liczbę, jaką mogą przechowywać: Integer w dziedzinie informatyki.
Jednak nawet przy standardowym kompilatorze C ++ można stosunkowo łatwo dowiedzieć się, używając następującego fragmentu kodu:
Dokumentację dla std :: numeric_limits można znaleźć na Roguewave . Zawiera mnóstwo innych poleceń, które można wywołać, aby poznać różne ograniczenia. Można tego używać z dowolnym dowolnym typem, który przekazuje rozmiar, na przykład std :: streamsize.
Odpowiedź Jana zawiera najlepszy opis, ponieważ są one gwarantowane. Bez względu na to, na jakiej platformie się znajdujesz, istnieje jeszcze jedna dobra strona, która zawiera bardziej szczegółowe informacje na temat liczby bitów każdego typu MUSI zawierać: typy int , które są zdefiniowane w standardzie.
Mam nadzieję, że to pomoże!
źródło
1) Tabela N1 w artykule „ Zapomniane problemy rozwoju programów 64-bitowych ”
2) „ Model danych ”
źródło
Możesz użyć:
datatype = int
,long int
itp. Będziesz mógł zobaczyć rozmiar dla dowolnego typu danych, który wpiszesz.źródło
Jeśli chodzi o typy wbudowane dla różnych architektur i różnych kompilatorów, po prostu uruchom następujący kod na swojej architekturze z kompilatorem, aby zobaczyć, co wyprowadza. Poniżej pokazano moje wyjście Ubuntu 13.04 (Raring Ringtail) 64-bitowe g ++ 4.7.3. Zwróć również uwagę na poniższe odpowiedzi, dlatego dane wyjściowe są zamawiane jako takie:
„Istnieje pięć standardowych typów liczb całkowitych ze znakiem: podpisany char, short int, int, long int i long long int. Na tej liście każdy typ zapewnia co najmniej tyle samo miejsca, co poprzedzające go na liście”.
źródło
sizeof(char)
nie powinien być uwzględniony.Jak wspomniano, rozmiar powinien odzwierciedlać obecną architekturę. Możesz
limits.h
sprawdzić, czy twój obecny kompilator radzi sobie z różnymi rzeczami.źródło
Jak odpowiedzieli inni, wszystkie „standardy” pozostawiają większość szczegółów jako „implementację zdefiniowaną” i tylko stwierdzają, że typ „char” jest co najmniej „char_bis” szeroki, a „char <= krótki <= int <= długi < = long long ”(liczba zmiennoprzecinkowa i liczba podwójna są prawie zgodne ze standardami zmiennoprzecinkowymi IEEE, a długość podwójna jest zwykle taka sama jak liczba podwójna - ale może być większa w przypadku bardziej aktualnych implementacji).
Jednym z powodów braku konkretnych i dokładnych wartości jest to, że języki takie jak C / C ++ zostały zaprojektowane tak, aby były przenośne na wiele platform sprzętowych - w tym systemy komputerowe, w których rozmiar słowa „char” może wynosić 4 bity lub 7-bitów, a nawet niektórych wartości innych niż komputery „8- / 16- / 32- / 64-bit”, na które narażony jest przeciętny użytkownik komputera domowego. (Rozmiar słowa w tym przypadku oznacza, ile bitów w całym systemie normalnie działa - Ponownie, nie zawsze jest to 8 bitów, jak mogą się spodziewać użytkownicy komputerów domowych).
Jeśli naprawdę potrzebujesz obiektu (w sensie serii bitów reprezentujących wartość całkowitą) o określonej liczbie bitów, większość kompilatorów ma jakąś metodę określenia tego; Ale na ogół nie jest przenośny, nawet między kompilatorami firmy ame, ale na różne platformy. Niektóre standardy i praktyki (szczególnie ograniczenia. Hi podobne) są na tyle powszechne, że większość kompilatorów będzie obsługiwać określanie typu najlepiej dopasowanego do określonego zakresu wartości, ale nie liczby używanych bitów. (To znaczy, jeśli wiesz, że musisz przechowywać wartości od 0 do 127, możesz ustalić, że twój kompilator obsługuje 8-bitowy typ „int8”, który będzie wystarczająco duży, aby pomieścić żądany pełny zakres, ale nie coś w rodzaju typ „int7”, który byłby dokładnym dopasowaniem dla 7 bitów.)
Uwaga: Wiele pakietów źródłowych Un * x używało skryptu „./configure”, który sprawdza możliwości kompilatora / systemu i wyświetla odpowiedni plik Makefile i config.h. Możesz zbadać niektóre z tych skryptów, aby zobaczyć, jak one działają i jak sprawdzają możliwości systemu kompilatora / systemu i podążają za nimi.
źródło
Jeśli jesteś zainteresowany czystym rozwiązaniem C ++, skorzystałem z szablonów i tylko standardowego kodu C ++ do definiowania typów w czasie kompilacji na podstawie ich wielkości bitów. Dzięki temu rozwiązanie jest przenośne dla różnych kompilatorów.
Pomysł jest bardzo prosty: utwórz listę zawierającą typy char, int, short, long, long long (wersje podpisane i niepodpisane), a następnie zeskanuj listę i za pomocą szablonu numeric_limits wybierz typ o danym rozmiarze.
Łącznie z tym nagłówkiem masz 8 typów stdtype :: int8, stdtype :: int16, stdtype :: int32, stdtype :: int64, stdtype :: uint8, stdtype :: uint16, stdtype :: uint32, stdtype :: uint64.
Jeśli jakiś typ nie może być reprezentowany, zostanie przetworzony na stdtype :: null_type również zadeklarowany w tym nagłówku.
PONIŻSZY KOD JEST UDANY BEZ GWARANCJI, PROSIMY O PODWÓJNE SPRAWDZENIE.
JESTEM NOWY W METAPROGRAMMINGU, ZAPRASZAMY DO EDYCJI I PRAWIDŁOWEGO TEGO KODU.
Testowane z DevC ++ (więc wersja gcc około 3.5)
źródło
gdzie
X
jestchar
,int
,long
etc .. daje rozmiarX
w bitach.źródło
sizeof(type)*CHAR_BIT
Trzyma tylkoCHAR_BIT
gwarantowane jest 8 bitów,<< 3
jest jedynie zaciemnionym sposobem pisania* 8
lub* CHAR_BIT
.Od Alex B Standard C ++ nie określa wielkości typów całkowych w bajtach, ale określa minimalne zakresy, które muszą być w stanie pomieścić. Możesz określić minimalny rozmiar w bitach z wymaganego zakresu. Na podstawie tego można wywnioskować minimalny rozmiar w bajtach oraz wartość makra CHAR_BIT, która definiuje liczbę bitów w bajcie (na wszystkich mało znanych platformach jest to 8 i nie może być mniejsza niż 8).
Dodatkowym ograniczeniem dla znaku jest to, że jego rozmiar wynosi zawsze 1 bajt lub bit CHAR_BIT (stąd nazwa).
Minimalne zakresy wymagane przez standard (strona 22) to:
i zakresy typów danych w MSDN:
podpisany znak: od -127 do 127 (uwaga, nie od -128 do 127; to dotyczy platform z uzupełnieniem 1) znak bez znaku: od 0 do 255 znak „zwykły”: od -127 do 127 lub od 0 do 255 (w zależności od domyślnej sygnatury znaku) podpisany krótki: od -32767 do 32767 bez znaku krótki: od 0 do 65535 podpisany int: -32767 do 32767 niepodpisany int: 0 do 65535 podpisany długi: -2147483647 do 2147483647 niepodpisany długi: od 0 do 4294967295 podpisany długi długi: -9223372036854775807 do 9223372036854775807 niepodpisany 0 do 18446744073709551615 Implementacja C ++ (lub C) może definiować rozmiar typu w bajtach sizeof (type) do dowolnej wartości, o ile
wyrażenie sizeof (typ) * CHAR_BIT ocenia na liczbę bitów wystarczającą do zawarcia wymaganych zakresów, a kolejność typów jest nadal ważna (np. sizeof (int) <= sizeof (long)). Rzeczywiste zakresy specyficzne dla implementacji można znaleźć w nagłówku w C lub w C ++ (lub jeszcze lepiej w szablonie std :: numeric_limits w nagłówku).
Na przykład, w ten sposób znajdziesz maksymalny zasięg dla int:
DO:
C ++:
Jest to jednak poprawne, masz rację mówiąc, że: char: 1 bajt krótki: 2 bajty int: 4 bajty długie: 4 bajty zmiennoprzecinkowe: 4 bajty podwójne: 8 bajtów
Ponieważ architektury 32-bitowe są nadal domyślne i najczęściej używane, i zachowały te standardowe rozmiary od czasów sprzed 32 bitów, kiedy pamięć była mniej dostępna, a dla kompatybilności wstecznej i standaryzacji pozostała taka sama. Nawet systemy 64-bitowe zwykle z nich korzystają i mają rozszerzenia / modyfikacje. Więcej informacji na ten temat:
http://en.cppreference.com/w/cpp/language/types
źródło
Zauważam, że wszystkie inne odpowiedzi tutaj koncentrowały się prawie wyłącznie na typach integralnych, podczas gdy pytający pytał także o zmiennoprzecinkowe.
Nie sądzę, aby wymagał tego standard C ++, ale kompilatory dla najpopularniejszych platform w dzisiejszych czasach generalnie stosują się do standardu IEEE754 pod względem liczb zmiennoprzecinkowych. Ten standard określa cztery typy binarnych liczb zmiennoprzecinkowych (a także niektóre formaty BCD, których nigdy nie widziałem w kompilatorach C ++):
Jak zatem mapuje się na typy C ++? Zasadniczo
float
wykorzystuje pojedynczą precyzję; tak więcsizeof(float) = 4
. Następniedouble
używa podwójnej precyzji (uważam, że to jest źródło nazwydouble
) ilong double
może to być podwójna lub poczwórna precyzja (w moim systemie jest czterokrotna, ale w systemach 32-bitowych może być podwójna). Nie znam żadnych kompilatorów, które oferują zmiennoprzecinkowe połowy precyzji.Podsumowując, jest to zwykle:
sizeof(float)
= 4sizeof(double)
= 8sizeof(long double)
= 8 lub 16źródło
Jak wspomniałeś - w dużej mierze zależy to od kompilatora i platformy. W tym celu sprawdź standard ANSI, http://home.att.net/~jackklein/c/inttypes.html
Oto kompilator Microsoft: Zakresy typów danych .
źródło
Możesz używać zmiennych dostarczanych przez biblioteki takie jak OpenGL , Qt itp.
Na przykład Qt zapewnia qint8 (gwarantowane 8-bitowe na wszystkich platformach obsługiwanych przez Qt), qint16, qint32, qint64, quint8, quint16, quint32, quint64 itp.
źródło
Na komputerze 64-bitowym:
źródło
int
jest 8 bajtów, ale drugi nie jest gwarantowany. Nic nie mówi, żechar
powinno to być tylko 8 bitów. Dozwolone jest to,sizeof(void*)==4
mimo że ma 64 bity.Istnieją cztery typy liczb całkowitych w zależności od rozmiaru:
źródło
short
,int
ilong
wszystkie 32-bitowe liczby całkowite.int
, a nie słowa „liczba całkowita”.