2009-10-23 12 views
9

Mam świadomość, że specyfikacja języka C nie dyktuje dokładnego rozmiaru każdego typu liczby całkowitej (np. int).Rozmiar int w C na różnych architekturach

Zastanawiam się: czy istnieje sposób w C (nie C++) do zdefiniowania typu całkowitego o określonym rozmiarze, który zapewnia, że ​​będzie on taki sam dla różnych architektur? Podobnych:

typedef int8 <an integer with 8 bits> 
typedef int16 <an integer with 16 bits> 

Lub w inny sposób, który pozwoli na kompilację innych części programu w innej architekturze.

+1

Twoje pytanie jest bardzo podobne do http://stackoverflow.com/questions/126279/c99-stdint-h-header-and-ms-visual-studio –

+2

@zilgo: Odpowiedź może być podobna; pytanie nie jest. W 126279 OP jest już świadomy stdint.h; NawaMan (widocznie) nie był, gdy zadaje pytanie. –

+2

Pamiętaj, że twoje ostatnie założenie jest błędne. Różnice w rozmiarze int niekoniecznie blokują kompilację na innych architekturach, ale ukryte założenia, takie jak 'i == i & 0xFFFFFFFF' mogą. Dobry programista pisze 'i 0xFFFF' kiedy chce matematyki modulo 2^16, i nie dba o to, czy' unsigned short' ma dokładnie 16 bitów. – MSalters

Odpowiedz

15

Co chcesz jest <stdint.h>, które kompilatory, które są zgodne ze standardem C ("C99") będzie realizować . Niestety nie dotyczy to Microsoft. Na szczęście projekt open source zapewnia <stdint.h> dla Windows, patrz msinttypes.

Umożliwi to korzystanie z int32_t i uint32_t oraz 8, 16 i 64 i wielu innych.

Uwaga: sam plik nagłówkowy nie jest opcjonalny w standardzie, jednak większość typów w nagłówku jest opcjonalnie opcjonalna. Niektóre nie są. Najpopularniejsze typy to te opcjonalne, ale nic nie powstrzyma cię od użycia wymaganych. Chodzi o to, że jeśli implementacja zapewnia nagłówek w ogóle, w praktyce definiują one wszystkie typy.

+0

Czy oznacza to, że jeśli zawsze kompiluję mój kod z kompilatorem C99 i zawsze włączam , to powinienem być pewien, że int32_t ma zawsze 4 bajty? – NawaMan

+0

@NawaMan - możesz być pewien, że 'int32_t' będzie miał dokładnie 32-bity. Jeśli platforma nie ma 32-bitowego typu int, kompilacja zakończy się niepowodzeniem, ponieważ typ 'int32_t' nie zostanie zdefiniowany. Ponadto wiele kompilatorów spoza C99 dostarcza 'stdint.h' - dla tych, którzy tego nie robią (Microsoft), możesz uzyskać jeden z kilku miejsc wskazanych w innych komentarzach/odpowiedziach, w tym: http://snipplr.com/view/ 18199/stdinth/ –

+0

@NawaMan: YES. Należy również zauważyć, że C99 daje minimum dla klasycznych typów: int> = 16, długie> = 32, długie długie> = 64. – DigitalRoss

13

C99, w stdint.h, definiuje typy takie jak int8_t i int16_t.

+0

Wierzę, że istnieje wersja, która obejmuje wiele innych platform, które również nie są zgodne z C99, ale nie jestem pewien. –

+0

MSVC nie lubi ''. Nie obchodzi mnie to, przestałem go używać ze względu na okropny kod-gen. – LiraNuna

+0

To interesujące. Czy mówisz, że nie ma stdint.h lub cstdint lub że nie ma int16_t, mimo że obsługuje typ o tej szerokości bitowej? To, jak sądzę, sprawi, że będzie niezgodna i wątpię, że stwardnienie rozsiane byłoby tak głupie. – paxdiablo

2

Jeśli nie sprawdzasz każdej platformy pod numerem #ifdef, wątpię, aby było to łatwe. Ale wiele bibliotek już to robi dla ciebie. Dla MSVC jest to __int8, __int16, &c. Biblioteka GTK ma podobne typy.

2

O ile mi wiadomo, odpowiedź brzmi nie. Kodujemy dla różnych platform i po prostu używamy typedefs dla konkretnych platform za pomocą # if/# else. Na przykład na Win32: typedef int int32;

Pozdrawiam,

Sebastiaan

5

Nie, średnia C określa minimalne rozmiary dla integralnych typach, ale nie daje żadnych gwarancji na maksymalnych rozmiarach.

Implementacja powinna zapewniać typy intN_t, jeśli typy o tym rozmiarze są dostępne. Wspominam tylko, że ponieważ masz tag między platformami - implementacja, która nie ma typu poprawnej szerokości bitowej, nie musi podawać tych typów.

Zazwyczaj można wybrać (z ustawieniami definiującymi, na przykład, cc -D_INT16_IS_INT i #ifdef s) poprawny typ, którego należy użyć dla określonego rozmiaru bitowego. Możesz opracować wymagane definicje dla każdej platformy, którą chcesz obsłużyć kodem C, używając CHAR_BIT i sizeof().

odpowiedniej części projektu C1X (n1362) wynosi:


7.18.1.1 Dokładna szerokości liczby całkowite

  1. Nazwa typedef intN_t oznacza podpisaną typu liczba całkowita szerokość N, brak bitów dopełnienia i reprezentacja uzupełnienia dwójki. Tak więc, int8_t oznacza liczbę całkowitą ze znakiem, o szerokości dokładnie 8 bitów.

  2. Nazwa typedef uintN_t oznacza niepodpisany typ całkowity o szerokości N. Tak więc, uint24_t oznacza niepodpisany typ liczby całkowitej o szerokości dokładnie 24 bitów.

  3. Te typy są opcjonalne. Jeśli jednak implementacja zapewnia typy całkowite o szerokości 8, 16, 32 lub 64-bitowe, bez bitów dopełniających i (dla typów podpisanych), które mają reprezentację uzupełnienia dwójkowego, to musi zdefiniować odpowiednie nazwy typedef.


dotyczące doboru rodzaju, coś jak to powinno wystarczyć:

#ifdef INT32_IS_SHORT 
    typedef short INT32 
#endif 
#ifdef INT32_IS_INT 
    typedef int INT32 
#endif 
#ifdef INT32_IS_LONG 
    typedef long INT32 
#endif 
+2

Jeśli chcesz zawieść, gdy system nie ma dokładnego rozmiaru, użyj po prostu 'int8_t' lub' int16_t' - kompilacja zakończy się niepowodzeniem, jeśli system ich nie posiada - nie ma potrzeby stosowania warunkowego kodu. Jeśli chcesz nie zawieść, ale zamiast tego użyj następnego najlepszego typu, użyj int_least8_t lub int_least16_t. –

+1

Preprocesor nie może ocenić "sizeof()". –

+0

Zgodnie ze standardem C99, długo musi być więcej niż 16-bitów;) –

0

Zawsze można napisać bibliotekę arytmetyczną, która używała wektorów niepodpisanych znaków dla liczb. W ten sposób możesz użyć liczb o dowolnej długości bitowej, a nawet pozwolić, by długość bitów była zmienna.

W rzeczywistości nie trzeba implementować takiej biblioteki, ponieważ GNU MP już to obsługuje.

http://gmplib.org/

2

Czasami warto spojrzeć na pstdint.h. Jest to przenośna implementacja stdint.h i nie wymaga obsługi kompilatora C99.