Czy rozmiar C jest „int” 2 bajty czy 4 bajty?

168

Czy zmienna typu Integer w C zajmuje 2 bajty czy 4 bajty? Od jakich czynników to zależy?

Większość podręczników mówi, że zmienne całkowite zajmują 2 bajty. Ale kiedy uruchamiam program wyświetlający kolejne adresy tablicy liczb całkowitych, pokazuje różnicę 4.

Rajiv Prathap
źródło
6
en.wikipedia.org/wiki/…
Evan Mulawski
1
intjest tylko jednym z kilku typów liczb całkowitych . Pytałeś o rozmiar „liczby całkowitej”; prawdopodobnie chciałeś zapytać o rozmiar int.
Keith Thompson,
3
Powinieneś znaleźć lepsze podręczniki. Podręcznik, który mówi, że a intma 2 bajty (a) prawdopodobnie odnosi się do starego systemu i (b) nie wyjaśnia, że ​​rozmiar będzie się różnił w zależności od systemu. Najlepszą książką na temat C jest „Język programowania C” autorstwa Kernighana i Ritchiego, chociaż zakłada pewne doświadczenie w programowaniu. Zobacz również pytanie 18.10 w comp.lang.c FAQ .
Keith Thompson,
2
Spróbuj #define int int64_tna platformie 64-bitowej, więc też nie. Po prostu użyj sizeof. ;-)
netcoder

Odpowiedzi:

183

Wiem, że to jest równe sizeof(int). Rozmiar pliku intjest naprawdę zależny od kompilatora. Dawno temu, kiedy procesory były 16-bitowe, wartość an intwynosiła 2 bajty. Obecnie jest to najczęściej 4 bajty w systemach 32-bitowych i 64-bitowych.

Mimo sizeof(int)to użycie jest najlepszym sposobem uzyskania rozmiaru liczby całkowitej dla określonego systemu, w którym program jest wykonywany.

EDYCJA: Naprawiono błędną instrukcję, która intma 8 bajtów w większości systemów 64-bitowych. Na przykład jest to 4 bajty w 64-bitowym GCC.

yhyrcanus
źródło
31
@RajivPrathap: Cóż, jest to zależne od kompilatora, ale kompilator decyduje, czy jest również zależny od komputera. :)
user541686
2
Jeśli potrzebujesz rozmiaru dla preprocesora, możesz sprawdzić wstępnie zdefiniowane makra, takie jak INT_MAX. Jeśli wartość nie jest tą, której oczekuje Twój kod, to rozmiar bajtu int jest inny w bieżącej kombinacji kompilator / platforma.
Walt Sellers
3
Nie tylko zależy od komputera, ale także od systemu operacyjnego uruchomionego na komputerze. Na przykład długość w Win64 to 4 bajty, podczas gdy długość w Linux64 to 8 bajtów.
Cem Kalyoncu
9
źle. w większości systemów 64-bitowych int to nadal 4 bajty en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models
phuclv
7
sizeof(int)może mieć dowolną wartość z 1. Bajt nie musi mieć 8 bitów, a niektóre maszyny nie mają 8-bitowej adresowalnej jednostki (co w zasadzie jest definicją bajtu w standardzie). Odpowiedź nie jest poprawna bez dalszych informacji.
zbyt szczery dla tej strony
102

Jest to jeden z punktów w C, który może być początkowo mylący, ale standard C określa tylko minimalny zakres dla typów całkowitych, które mają być obsługiwane. intgwarantuje, że będzie w stanie przechowywać od -32767 do 32767, co wymaga 16 bitów. W tym przypadku int, wynosi 2 bajty. Jednak implementacje mogą wykraczać poza to minimum, ponieważ zobaczysz, że wiele współczesnych kompilatorów tworzy int32-bitowe (co również oznacza 4 bajty dość wszechobecne).

Powodem, dla którego twoja książka podaje 2 bajty, jest najprawdopodobniej to, że jest stara. Kiedyś była to norma. Ogólnie rzecz biorąc, zawsze powinieneś używać sizeofoperatora, jeśli chcesz dowiedzieć się, ile bajtów znajduje się na używanej platformie.

Aby rozwiązać ten problem, C99 dodał nowe typy, w których można jawnie poprosić o określoną liczbę całkowitą, na przykład int16_tlub int32_t. Wcześniej nie było uniwersalnego sposobu na uzyskanie liczby całkowitej o określonej szerokości (chociaż większość platform udostępniała podobne typy dla każdej platformy).

Błąd krytyczny
źródło
7
@nevanking: Na maszynie z dopełnieniem dwójki (czyli każdej maszynie, którą znam ...), tak. Ale C nie gwarantuje, że tak się stanie.
FatalError
@nevanking Jestem zupełnie nowy w C, ale czy nie jest to 32767, ponieważ w przeciwnym razie używałby innego bitu | bajtu? Wyobraź sobie, że mogę przechowywać 3 cyfry (0 lub 1), więc mogę przejść od 000 do 111 (czyli 7 dziesiętnie). 7 jest tuż przed wykładnikiem 2. Gdybym mógł przejść do 8 (1000), mógłbym użyć tych 4 cyfr aż do 15! Na przykład 32767 znajduje się tuż przed wykładnikiem 2, wyczerpując wszystkie dostępne bity | bajtów.
RGS
3
@RSerrao Nie jestem też ekspertem od C, ale AFAIK dla liczb dodatnich to o jeden mniej niż maksymalna liczba ujemna. A więc od -8 do 7, od -256 do 255 i tak dalej. Liczby ujemne nie muszą liczyć zera.
nevan king
1
„16 bitów. W takim przypadku int, to 2 bajty” może być błędne, jeśli CHAR_BIT to 16, sizeof (int) może wynosić 1 bajt (lub znak).
12431234123412341234123
6
@nevanking: tylko jeśli przyjmiesz reprezentację uzupełnienia 2 dla podpisanych int. C nie przyjmuje takiego założenia. Systemy dopełnienia i wielkości znaku 1 nie mogą reprezentować -3276816 bitów; raczej mają dwie reprezentacje dla zera (dodatnią i ujemną). Dlatego minimalny zasięg intto [-32767..32767].
John Bode
33

Nie ma konkretnej odpowiedzi. To zależy od platformy. Jest zdefiniowany w ramach implementacji. Może to być 2, 4 lub coś innego.

Idea stojąca za int polegał na tym, że miał on odpowiadać naturalnemu rozmiarowi „słowa” na danej platformie: 16 bitów na platformach 16-bitowych, 32 bity na platformach 32-bitowych, 64 bity na platformach 64-bitowych, masz pomysł. Jednak ze względu na kompatybilność wsteczną niektóre kompilatory wolą trzymać się wersji 32-bitowej, intnawet na platformach 64-bitowych.

Czas 2-bajtowy intjuż dawno minął (platformy 16-bitowe?), Chyba że używasz jakiejś wbudowanej platformy z 16-bitowym rozmiarem słowa. Twoje podręczniki są prawdopodobnie bardzo stare.

Mrówka
źródło
2
The idea behind int was that it was supposed to match the natural "word" size on the given platform- To jest to, czego szukałem. Masz pojęcie, jaki może być powód? W wolnym świecie int może zajmować dowolną liczbę kolejnych bajtów w pamięci, prawda? 8, 16 cokolwiek
bholagabbar
19

Odpowiedź na to pytanie zależy od używanej platformy.
Ale niezależnie od platformy możesz niezawodnie założyć następujące typy:

 [8-bit] signed char: -127 to 127
 [8-bit] unsigned char: 0 to 255
 [16-bit]signed short: -32767 to 32767
 [16-bit]unsigned short: 0 to 65535
 [32-bit]signed long: -2147483647 to 2147483647
 [32-bit]unsigned long: 0 to 4294967295
 [64-bit]signed long long: -9223372036854775807 to 9223372036854775807
 [64-bit]unsigned long long: 0 to 18446744073709551615
Priyank Arora
źródło
3
Ktoś zmodyfikował Twój post, aby „naprawić” zakresy, ale nie jestem pewien, czy Twoja edycja odpowiednio odzwierciedla Twoje zamiary. Zakłada implementację uzupełnienia do dwóch, co będzie prawdą w większości przypadków, ale nie we wszystkich. Ponieważ Twoja odpowiedź wyraźnie wskazuje na zależność od implementacji, myślę, że edycja jest prawdopodobnie błędna. Jeśli się zgadzasz, pamiętaj, aby cofnąć zmianę.
Cody Grey
1
@ k06a Twoja edycja była nieprawidłowa . Specjalnie zmieniłeś oryginalne zakresy na zakresy z dwoma dopełnieniami - nie są to te określone w standardzie C.
Antti Haapala
@CodyGray to zmieniało się w tę iz powrotem, będąc zgodne z uzupełnieniem 1 przez ostatnie 3 lata i OP nic nie mówił, więc przywróciłem edycję, która zmieniła ją na uzupełnienie 2 z „ustalonymi zakresami”, ponieważ mówi „możesz wiarygodnie założyć” , co nadal nie jest do końca prawdą.
Antti Haapala
13

Czy zmienna typu Integer w C zajmuje 2 bajty czy 4 bajty?

To zależy od używanej platformy, a także od konfiguracji kompilatora. Jedyną miarodajną odpowiedzią jest użycie sizeofoperatora, aby zobaczyć, jak duża jest liczba całkowita w konkretnej sytuacji.


Od jakich czynników to zależy?

Najlepiej rozważyć zasięg , a nie rozmiar . Oba będą się różnić w praktyce, chociaż, jak zobaczymy, znacznie bardziej niezawodnym jest wybieranie typów zmiennych według zakresu niż rozmiaru. Należy również zauważyć, że standard zachęca nas do rozważenia wyboru typów liczb całkowitych na podstawie zakresu a nie rozmiar , ale na razie zignorujmy standardową praktykę i pozwól naszej ciekawości zbadać sizeof, bajty i CHAR_BITreprezentacje liczb całkowitych ... królicza nora i zobacz to na własne oczy ...


sizeof, bajty i CHAR_BIT

Poniższe stwierdzenie, zaczerpnięte ze standardu C (do którego link znajduje się powyżej), opisuje to słowami, których nie sądzę, aby można było poprawić.

sizeofOperator uzyskuje rozmiar (w bajtach) jej argumentu operacji, który może być ekspresja lub nawiasach nazwa typu. Rozmiar jest określany na podstawie typu operandu.

Zakładając, że jasne zrozumienie doprowadzi nas do dyskusji na temat bajtów . W rzeczywistości przyjmuje się, że bajt to osiem bitówCHAR_BIT mówi ci, ile bitów jest w bajcie . To tylko kolejny z tych niuansów, których nie bierze się pod uwagę, gdy mówimy o typowych dwu- (lub czterobajtowych) liczbach całkowitych .

Podsumujmy do tej pory:

  • sizeof => rozmiar w bajtach i
  • CHAR_BIT => liczba bitów w bajcie

Tak więc, w zależności od systemu, sizeof (unsigned int)może to być dowolna wartość większa od zera (nie tylko 2 lub 4), jak gdyby wynosiła CHAR_BIT16, wtedy pojedynczy (szesnastobitowy) bajt ma wystarczającą liczbę bitów, aby reprezentować szesnastobitową liczbę całkowitą opisaną przez norm (cytowane poniżej). To niekoniecznie przydatne informacje, prawda? Zanurzmy się głębiej ...


Reprezentacja liczb całkowitych

Ç Określono minimalne dokładności / zakres dla standardowych typów całkowitych (a CHAR_BIT, także FWIW) tutaj . Na tej podstawie możemy wyliczyć minimalną liczbę bitów potrzebnych do przechowywania wartości , ale równie dobrze możemy po prostu wybrać nasze zmienne na podstawie zakresów . Niemniej jednak ogromna część szczegółów wymaganych dla tej odpowiedzi znajduje się tutaj. Na przykład następujące, które standard unsigned intwymaga (co najmniej) szesnastu bitów pamięci:

UINT_MAX                                65535 // 2¹⁶ - 1

W ten sposób widzimy, że unsigned intwymaga ( co najmniej ) 16 bitów , czyli tam, gdzie otrzymujesz dwa bajty (zakładając, że CHAR_BITjest to 8) ... a później, gdy limit wzrósł do 2³² - 1, ludzie podawali zamiast tego 4 bajty. To wyjaśnia obserwowane przez Ciebie zjawiska:

Większość podręczników mówi, że zmienne całkowite zajmują 2 bajty. Ale kiedy uruchamiam program wyświetlający kolejne adresy tablicy liczb całkowitych, pokazuje różnicę 4.

Używasz starożytnego podręcznika i kompilatora, który uczy cię nieprzenośnego języka C; autor, który napisał twój podręcznik, może nawet nie być tego świadomy CHAR_BIT. Ci powinni uaktualnić swój podręcznik (i kompilatora), i staramy się pamiętać, że to ciągle rozwijająca się dziedzina, że trzeba się zatrzymać przed konkurować ... dość o tym, choć; zobaczmy, jakie inne nieprzenośne sekrety leżą u podstaw bajtów całkowitych przechowują ...

Wydaje się, że liczą się bity wartości . W powyższym przykładzie zastosowano plikunsigned całkowitego, który zazwyczaj zawiera tylko bity wartości, więc łatwo przeoczyć diabła w szczegółach.

Sign bits ... W powyższym przykładzie zacytowałem UINT_MAXjako górną granicę, unsigned intponieważ jest to trywialny przykład wyodrębnienia wartości 16z komentarza. W przypadku typów ze znakiem, aby rozróżnić wartości dodatnie i ujemne (to jest znak), musimy również dołączyć bit znaku.

INT_MIN                                -32768 // -(2¹⁵)
INT_MAX                                +32767 // 2¹⁵ - 1

Wypełnianie bitów ... Chociaż nie jest powszechne napotykanie komputerów, które mają dopełnianie bitów w liczbach całkowitych, standard C pozwala na to; niektóre maszyny (np. ta ) implementują większe typy liczb całkowitych, łącząc ze sobą dwie mniejsze (ze znakiem) wartości całkowite ... a kiedy łączysz liczby całkowite ze znakiem, otrzymujesz zmarnowany bit znaku. Ten zmarnowany bit jest uważany za wypełnienie w C. Inne przykłady bitów wypełnienia mogą obejmować bity parzystości i bity pułapki .


Jak widać, standard wydaje się zachęcać do rozważania zakresów, takich jak INT_MIN... INT_MAXi innych wartości minimalnych / maksymalnych ze standardu przy wyborze typów całkowitych, i zniechęca do polegania na rozmiarach, ponieważ istnieją inne subtelne czynniki, które mogą zostać zapomniane, takie jak CHAR_BITi wypełnianie bitów, które może wpływać na wartość sizeof (int)(tj. powszechne nieporozumienia dotyczące dwu- i czterobajtowych liczb całkowitych pomijają te szczegóły).

Flimzy
źródło
13

Projekt standardowy C99 N1256

http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

Rozmiar inti wszystkie inne typy liczb całkowitych są zdefiniowane w implementacji, C99 określa tylko:

  • gwarancje minimalnego rozmiaru
  • względne rozmiary między typami

5.2.4.2.1 „Rozmiary typów całkowitych <limits.h>” podaje minimalne rozmiary:

1 [...] Ich wartości określone w ramach realizacji muszą być co najmniej równe wielkości (wartość bezwzględna) tym przedstawionym [...]

  • UCHAR_MAX 255 // 2 8 - 1
  • USHRT_MAX 65535 // 2 16 - 1
  • UINT_MAX 65535 // 2 16 - 1
  • ULONG_MAX 4294967295 // 2 32 - 1
  • ULLONG_MAX 18446744073709551615 // 2 64 - 1

6.2.5 „Typy” mówi wtedy:

8 Dla dowolnych dwóch typów liczb całkowitych z tym samym znakiem i różnym stopniem konwersji liczb całkowitych (patrz 6.3.1.1), zakres wartości typu z mniejszą rangą konwersji liczb całkowitych jest podzakresem wartości drugiego typu.

oraz 6.3.1.1 „Boolean, znaki i liczby całkowite” określa względne stopnie konwersji:

1 Każdy typ liczb całkowitych ma rangę konwersji liczb całkowitych zdefiniowaną w następujący sposób:

  • Stopień long long int będzie wyższy niż stopień long int, który będzie większy niż stopień int, który będzie większy niż stopień short int, który będzie większy niż stopień podpisanego char.
  • Pozycja dowolnego typu liczby całkowitej bez znaku jest równa randze odpowiedniego typu liczby całkowitej ze znakiem, jeśli istnieje.
  • Dla wszystkich typów całkowitych T1, T2 i T3, jeśli T1 ma wyższą rangę niż T2, a T2 ma wyższą rangę niż T3, to T1 ma wyższą rangę niż T3
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
źródło
8

Jedyne gwarancje to, że charmusi mieć co najmniej 8 bitów szerokości shorti intmusi mieć co najmniej 16 bitów szerokości i longmusi mieć co najmniej 32 bity szerokości oraz że sizeof (char)<= sizeof (short)<= sizeof (int)<= sizeof (long)(to samo dotyczy wersji bez znaku tych typów ).

int może mieć szerokość od 16 do 64 bitów w zależności od platformy.

John Bode
źródło
6

Czy rozmiar C jest „int” 2 bajty czy 4 bajty?

Odpowiedź brzmi „tak” / „nie” / „może” / „może nie”.

Język programowania C określa, co następuje: najmniejsza adresowalna jednostka, znana chari nazywana „bajtem” , ma dokładnie CHAR_BITszerokość bitów, gdzieCHAR_BIT wynosi co najmniej 8.

Zatem jeden bajt w C niekoniecznie jest oktetem , czyli 8 bitów. W przeszłości jedna z pierwszych platform do uruchamiania kodu C (i Unix) miała 4-bajtowe int- ale w sumie intmiała 36 bitów, ponieważ CHAR_BITbyło ich 9!

intma być naturalną liczbą całkowitą dla platformy, która ma zakres co najmniej-32767 ... 32767 . Możesz uzyskać rozmiar intw bajtach platformy za pomocą sizeof(int); kiedy pomnożymy tę wartość przez CHAR_BIT, będziecie wiedzieć, jak szeroka jest ona w bitach.


Podczas gdy maszyny 36-bitowe są w większości martwe, nadal istnieją platformy z bajtami innymi niż 8-bitowe. Jeszcze wczoraj pojawiło się pytanie o mikrokontroler Texas Instruments z 16-bitowymi bajtami , który ma kompilator zgodny z C99, C11.

Na TMS320C28x wydaje się, że char, shorti intwszystkie 16 bitów szerokości, a więc jednego bajta. long intto 2 bajty i long long int4 bajty. Piękno C polega na tym, że wciąż można napisać wydajny program dla takiej platformy, a nawet zrobić to w sposób przenośny!

Antti Haapala
źródło
„ponieważ CHAR_BIT miał 9 lat!” - Mieli wtedy 362880 bitów obliczeniowych !? Imponujący.
Josh Desmond
5

W większości zależy to od używanej platformy, od kompilatora do kompilatora, obecnie w większości kompilatorów int ma 4 bajty . Jeśli chcesz sprawdzić, czego używa Twój kompilator, możesz użyć sizeof(int).

main()
{
    printf("%d",sizeof(int));
    printf("%d",sizeof(short));
    printf("%d",sizeof(long));
}

Jedyną obietnicą kompilatora c jest to, że rozmiar short musi być równy lub mniejszy niż int, a rozmiar long musi być równy lub większy niż int. Więc jeśli rozmiar int wynosi 4, to rozmiar short może wynosić 2 lub 4, ale nie większy niż to. To samo jest prawdziwe dla długich i int. Mówi się również, że rozmiar krótki i długi nie mogą być takie same.

justpraveen
źródło
1
Korzystanie %dprzez size_tparametr jest UB.
Paul R
3

Zależy to od implementacji, ale zwykle na x86 i innych popularnych architekturach, takich jak ARM, intzajmuje 4 bajty. Zawsze możesz to sprawdzić w czasie kompilacji, używając sizeof(int)lub dowolnego innego typu, który chcesz sprawdzić.

Jeśli chcesz mieć pewność, że używasz typu o określonym rozmiarze, użyj typów w <stdint.h>

slartibartfast
źródło
2
#include <stdio.h>

int main(void) {
    printf("size of int: %d", (int)sizeof(int));
    return 0;
}

Zwraca 4, ale prawdopodobnie zależy od komputera.

prawa
źródło
1

Czy rozmiar C jest „int” 2 bajty czy 4 bajty?

Czy zmienna typu Integer w C zajmuje 2 bajty czy 4 bajty?

C pozwala, aby „bajty” były czymś innym niż 8 bitów na „bajt”.

CHAR_BIT liczba bitów dla najmniejszego obiektu, który nie jest polem bitowym (bajtem) C11dr §5.2.4.2.1 1

Wartość wyższa niż 8 jest coraz rzadsza. Aby zapewnić maksymalną przenośność, użyj CHAR_BITzamiast 8. Rozmiar intw bitach w C wynosi sizeof(int) * CHAR_BIT.

#include <limits.h>
printf("(int) Bit size %zu\n", sizeof(int) * CHAR_BIT);

Od jakich czynników to zależy?

Rozmiar intbitu to zwykle 32 lub 16 bitów. C określone minimalne zakresy :

minimalna wartość dla obiektu typu int INT_MIN-32767
maksymalna wartość dla obiektu typu int INT_MAX+32767
C11dr §5.2.4.2.1 1

Minimalny zakres dla intsił Wielkość bitowa być co najmniej 16 - nawet w przypadku, gdy procesor jest „8-bitowa”. Rozmiar podobny do 64 bitów występuje w wyspecjalizowanych procesorach. Inne wartości, takie jak 18, 24, 36 itd., Wystąpiły na platformach historycznych lub są przynajmniej teoretycznie możliwe. Współczesne kodowanie rzadko martwi się o introzmiary bitów inne niż potęga 2 .

Procesor i architektura komputera decydują o intwyborze rozmiaru bitu.

Jednak nawet w przypadku procesorów 64-bitowych introzmiar kompilatora może być 32-bitowy ze względu na kompatybilność, ponieważ duże bazy kodu zależą od int32-bitowego (lub 32/16).

chux - Przywróć Monikę
źródło
-1

To jest dobre źródło odpowiedzi na to pytanie.

Ale to pytanie jest zawsze prawdziwą odpowiedzią „Tak. Obie”.

To zależy od Twojej architektury. Jeśli zamierzasz pracować na komputerze 16-bitowym lub mniejszym, nie może to być 4 bajty (= 32 bity). Jeśli pracujesz na komputerze 32-bitowym lub lepszym, jego długość wynosi 32-bit.

Aby to zrozumieć, przygotuj program do wypisywania czegoś czytelnego i użyj funkcji „sizeof”. To zwraca rozmiar w bajtach zadeklarowanego typu danych. Ale bądź ostrożny, używając tego z tablicami.

Jeśli deklarujesz int t[12];, zwróci to 12 * 4 bajty. Aby uzyskać długość tej tablicy, po prostu użyj sizeof(t)/sizeof(t[0]). Jeśli masz zamiar zbudować funkcję, która powinna obliczyć rozmiar tablicy wysyłania, pamiętaj, że if

typedef int array[12];
int function(array t){
    int size_of_t = sizeof(t)/sizeof(t[0]);
    return size_of_t;
}
void main(){
    array t = {1,1,1};  //remember: t= [1,1,1,0,...,0]
    int a = function(t);    //remember: sending t is just a pointer and equal to int* t
   print(a);   // output will be 1, since t will be interpreted as an int itselve. 
}

Więc to nawet nie zwróci czegoś innego. Jeśli zdefiniujesz tablicę i później spróbujesz uzyskać długość, użyj sizeof. Jeśli wysyłasz tablicę do funkcji, pamiętaj, że wysyłana wartość jest tylko wskaźnikiem na pierwszym elemencie. Ale w pierwszym przypadku zawsze wiesz, jaki rozmiar ma twoja tablica. Przypadek drugi można zrozumieć, definiując dwie funkcje i tracić pewną wydajność. Zdefiniuj funkcję (tablica t) i zdefiniuj funkcję2 (tablica t, int size_of_t). Wywołaj "function (t)", zmierz długość za pomocą jakiegoś kopiowania i wyślij wynik do function2, gdzie możesz zrobić, co chcesz, na zmiennych rozmiarach tablic.

Shalec
źródło
Podany link jest złym źródłem informacji, ponieważ zakłada rzeczy, które nie zawsze są prawdziwe (np. charJest zawsze signed)
Andrei Damian-Fekete