2009-10-23 43 views
9

Tôi biết rằng đặc tả của ngôn ngữ C không quy định kích thước chính xác của từng loại số nguyên (ví dụ: int).Kích cỡ int trong C trên các kiến ​​trúc khác nhau

Điều tôi thắc mắc là: Có cách nào trong C (không phải C++) để xác định loại số nguyên với kích thước cụ thể đảm bảo nó sẽ giống nhau trên các kiến ​​trúc khác nhau không? Giống như:

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

Hoặc bất kỳ cách nào khác sẽ cho phép các phần khác của chương trình được biên dịch trên kiến ​​trúc khác nhau.

+1

Câu hỏi của bạn rất giống với http://stackoverflow.com/questions/126279/c99-stdint-h-header-and-ms-visual-studio –

+2

@zilgo: Câu trả lời có thể tương tự; câu hỏi là không. Trong 126279, OP đã nhận thức được stdint.h; NawaMan (rõ ràng) không phải là khi đặt câu hỏi. –

+2

Lưu ý rằng giả định cuối cùng của bạn là sai. Sự khác biệt về kích thước của một int không nhất thiết phải chặn biên dịch trên các kiến ​​trúc khác, nhưng các giả định tiềm ẩn như 'i == i & 0xFFFFFFFF' có thể. Một lập trình viên giỏi viết '& 0xFFFF' khi anh ta muốn toán học modulo 2^16, và không quan tâm liệu 'unsigned short' có chính xác 16 bit hay không. – MSalters

Trả lời

15

gì bạn muốn là <stdint.h>, mà trình biên dịch mà phù hợp với các tiêu chuẩn C ("C99") sẽ thực hiện . Thật không may, điều này không bao gồm Microsoft. May mắn thay, một dự án mã nguồn mở cung cấp một <stdint.h> cho Windows, xem msinttypes.

Điều này sẽ cho phép bạn sử dụng int32_tuint32_t, cộng với 8, 16 và 64 và nhiều loại khác.

Lưu ý: chính tệp tiêu đề không phải là tùy chọn trong tiêu chuẩn, tuy nhiên, hầu hết các loại trong tiêu đề là tùy chọn riêng lẻ. Một số thì không. Các loại được sử dụng phổ biến nhất là các loại tùy chọn, nhưng không có gì ngăn bạn sử dụng các loại được yêu cầu. Vấn đề là, nếu một thực hiện cung cấp tiêu đề ở tất cả, trong thực tế họ xác định tất cả các loại.

+0

Điều này có nghĩa rằng nếu tôi luôn biên dịch mã của tôi bằng trình biên dịch C99 và luôn bao gồm , tôi phải chắc chắn rằng int32_t luôn là 4 byte? – NawaMan

+0

@NawaMan - bạn có thể chắc chắn rằng 'int32_t' sẽ có chính xác 32 bit. Nếu nền tảng không có kiểu int 32 bit, thì biên dịch sẽ thất bại vì kiểu 'int32_t' sẽ không được định nghĩa. Ngoài ra, nhiều trình biên dịch không phải C99 cung cấp một 'stdint.h' - đối với những người không (Microsoft), bạn có thể lấy một từ một vài nơi được trỏ đến trong các nhận xét/câu trả lời khác bao gồm: http://snipplr.com/view/ 18199/stdinth/ –

+0

@NawaMan: CÓ. Cũng cần lưu ý rằng C99 cho bạn mức tối thiểu cho các loại cổ điển: int> = 16, dài> = 32, dài>> 64. – DigitalRoss

13

C99, trong stdint.h, xác định các loại như int8_tint16_t.

+0

Tôi tin rằng có một phiên bản bao gồm nhiều nền tảng khác không phù hợp với C99, nhưng tôi không chắc chắn. –

+0

MSVC không thích ' '. Không phải là tôi quan tâm, tôi đã ngừng sử dụng nó vì mã nguồn kinh khủng. – LiraNuna

+0

Điều đó thật thú vị. Bạn đang nói rằng nó không có stdint.h hoặc cstdint hoặc rằng nó không có int16_t mặc dù nó hỗ trợ một loại với chiều rộng bit? Điều đó, tôi nghĩ rằng, làm cho nó không phù hợp, và tôi nghi ngờ MS sẽ là ngu ngốc. – paxdiablo

2

Trừ khi bạn kiểm tra từng nền tảng với #ifdef hoặc hơn, tôi nghi ngờ việc này có thể dễ dàng. Nhưng nhiều thư viện đã làm nhiệm vụ đó cho bạn. Đối với MSVC nó là __int8, __int16, &c. Thư viện GTK có typedefs tương tự.

2

Theo như tôi biết câu trả lời là không. Chúng tôi viết mã cho các nền tảng khác nhau và chúng tôi chỉ sử dụng typedef cho các nền tảng cụ thể bằng # if/# else. Ví dụ trên Win32: typedef int int32;

Kính trọng,

Sebastiaan

5

Không, tiêu chuẩn C xác định kích thước tối thiểu đối với loại không thể thiếu nhưng không đảm bảo về kích thước tối đa.

Việc triển khai sẽ cung cấp các loại intN_t nếu các loại kích thước đó có sẵn. Tôi chỉ đề cập rằng vì bạn có một thẻ đa nền tảng - việc triển khai không có loại chiều rộng bit chính xác không cần phải cung cấp các loại đó.

Bạn thường có thể chọn (với cài đặt xác định bằng, ví dụ: cc -D_INT16_IS_INT#ifdef s) loại chính xác để sử dụng cho kích thước bit cụ thể. Bạn có thể tìm ra các định nghĩa bắt buộc cho từng nền tảng bạn muốn hỗ trợ bằng mã C bằng cách sử dụng CHAR_BITsizeof().

Các phần có liên quan của dự thảo c1x (n1362) là:

loại nguyên

7.18.1.1 Exact-width

  1. Tên typedef intN_t chỉ định một loại nguyên ký kết với chiều rộng N, không có bit đệm và biểu diễn bổ sung của hai. Do đó, int8_t biểu thị loại số nguyên đã ký với chiều rộng chính xác 8 bit.

  2. Tên typedef uintN_t chỉ định loại số nguyên không dấu có chiều rộng N. Do đó, uint24_t biểu thị một loại số nguyên không dấu có chiều rộng chính xác là 24 bit.

  3. Các loại này là tùy chọn. Tuy nhiên, nếu triển khai cung cấp các kiểu số nguyên với chiều rộng là 8, 16, 32 hoặc 64 bit, không có bit đệm và (đối với các loại đã ký) có biểu diễn bổ sung của hai, nó sẽ xác định tên typedef tương ứng.


Về việc lựa chọn các loại, một cái gì đó như thế này là đủ:

#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

Nếu bạn muốn thất bại khi hệ thống không có kích thước chính xác, sau đó chỉ cần sử dụng 'int8_t' hoặc' int16_t' - việc xây dựng sẽ thất bại nếu hệ thống không có chúng - không cần mã điều kiện. Nếu bạn không muốn thất bại nhưng sử dụng loại tốt nhất tiếp theo thay vào đó, hãy sử dụng int_least8_t hoặc int_least16_t. –

+1

Bộ tiền xử lý không thể đánh giá 'sizeof()'. –

+0

Theo tiêu chuẩn C99, dài phải hơn 16 bit;) –

0

Bạn luôn có thể viết một thư viện số học sử dụng vectơ của ký tự chưa ký cho các số. Bằng cách đó bạn có thể sử dụng số lượng của bất kỳ chiều dài bit nào bạn muốn và thậm chí cho phép độ dài bit thay đổi.

Thực ra, bạn không cần triển khai thư viện như vậy vì GNU MP đã xử lý việc này rồi.

http://gmplib.org/

2

Bạn có thể muốn có một cái nhìn tại pstdint.h. Nó là một thực hiện di động của stdint.h, và không yêu cầu hỗ trợ trình biên dịch C99.

Các vấn đề liên quan