Sự khác biệt giữa int và long trong C ++ là gì?


120

Đúng nếu tôi đã sai lầm,

int là 4 byte, với phạm vi giá trị từ -2,147,483,648 đến 2,147,483,647 (2 ^ 31)
dài là 4 byte, với dải giá trị từ -2,147,483,648 đến 2,147,483,647 (2 ^ 31)

Sự khác biệt trong C ++ là gì? Chúng có thể được sử dụng thay thế cho nhau không?


Trong VS2005 của tôi chạy trên bộ xử lý 32 bit, kích thước mặc định của int là 4 byte.


Nếu bạn muốn viết mã di động, hãy xem xét sử dụng #include <stdint.h>và sau đó là các loại cho biết kích thước. Vd uint32_t. Trên một nền tảng mới, sau đó bạn chỉ cần đảm bảo rằng stdint.h sử dụng đúng cho nền tảng cụ thể đó và mã của bạn hoạt động như dự định.
BitTickler

Câu trả lời:


112

Nó phụ thuộc vào việc thực hiện.

Ví dụ, trong Windows, chúng giống nhau, nhưng ví dụ trên hệ thống Alpha, chiều dài là 64 bit trong khi int là 32 bit. Bài viết này trình bày các quy tắc dành cho trình biên dịch Intel C ++ trên các nền tảng biến đổi. Tóm lại:

  OS           arch           size
Windows       IA-32        4 bytes
Windows       Intel 64     4 bytes
Windows       IA-64        4 bytes
Linux         IA-32        4 bytes
Linux         Intel 64     8 bytes
Linux         IA-64        8 bytes
Mac OS X      IA-32        4 bytes
Mac OS X      Intel 64     8 bytes  

Tôi nghĩ chúng ta nên xem xét kết hợp câu trả lời này (một câu trả lời theo ví dụ) với một số chi tiết bên dưới liên quan đến tiêu chuẩn C ++. Bản nháp cho C ++ 0x có tại open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2798.pdf và nó được đánh dấu để bạn có thể thấy sự khác biệt giữa nó và bản sửa đổi trước.
Patrick Johnmeyer

Bao gồm một cái gì đó theo thứ tự kích thước tương đối khôn ngoan của các loại mang lại nhiều thông tin hơn là liệt kê các kích thước cho các nền tảng khác nhau - như @Kevin trạng thái rất độc đáo. (-1vote)
xtofl

2
Một số trình biên dịch thậm chí còn có cờ cho phép bạn sửa đổi kích thước mặc định của int và long, tức là buộc chúng thành 8 hoặc 16, v.v. Xem tài liệu trình biên dịch để biết chi tiết.
Martin York

7
NB rằng đây là kích thước của lâu
rogerdpack

1
Vui lòng bao gồm cả kích thước của int.
cegprakash

82

Đảm bảo duy nhất bạn có là:

sizeof(char) == 1
sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)

// FROM @KTC. The C++ standard also has:
sizeof(signed char)   == 1
sizeof(unsigned char) == 1

// NOTE: These size are not specified explicitly in the standard.
//       They are implied by the minimum/maximum values that MUST be supported
//       for the type. These limits are defined in limits.h
sizeof(short)     * CHAR_BIT >= 16
sizeof(int)       * CHAR_BIT >= 16
sizeof(long)      * CHAR_BIT >= 32
sizeof(long long) * CHAR_BIT >= 64
CHAR_BIT         >= 8   // Number of bits in a byte

Cũng xem: longđược đảm bảo là ít nhất 32 bit không?


1
Hmm, điều này không đúng, nếu sizeof (ngắn)> = sizeof (char), chúng ta chỉ biết rằng sizeof (ngắn)> = 1 (không phải> = 2), btw dùng cho tất cả các loại. Theo sizeof này (bất kỳ loại tích phân nào)> = 1. Điều nào đúng, ví dụ: tôi nhớ sizeof (int) == 1 trên Z80, nhưng không có đảm bảo nào mạnh hơn trong thời gian dài?
Andreas Magnusson

6
3.9.1.2 của tiêu chuẩn C ++ chỉ định rằng sizeof (dài)> = sizeof (int)> = sizeof (short)> = sizeof (char) 5.3.3.1 của tiêu chuẩn C ++ chỉ định rằng sizeof (char), sizeof (unsigned char) và sizeof (ký tự ký hiệu) bằng 1. (tiếp ...)
KTC

4
(... tt) Các giá trị lớn nhất và nhỏ nhất có thể biểu diễn bằng các kiểu tích phân được định nghĩa là macro trong <giới hạn.h> (và do đó <climits>). Phụ lục E của tiêu chuẩn C (1990), được bao gồm bởi tham chiếu từ tiêu chuẩn C ++, quy định độ lớn tối thiểu của các macro này. (tiếp ...)
KTC

4
(... tiếp) và chúng là (2 ^ 15) -1, (2 ^ 15) -1, (2 ^ 31) -1, viết tắt, int và long tương ứng, hoạt động trở thành giá trị như được Martin York đăng trong phản hồi của anh ấy tại đây nếu CHAR_BIT là 8 (cũng là giá trị tối thiểu của nó).
KTC

2
@Giles: Đó không phải là những gì tôi đã nói ở trên? sizeof (short) * CHAR_BITS> = 16. Plust một vài thứ khác. :-)
Martin York

13

Khi biên dịch cho x64, sự khác biệt giữa int và long nằm trong khoảng từ 0 đến 4 byte, tùy thuộc vào trình biên dịch bạn sử dụng.

GCC sử dụng mô hình LP64, có nghĩa là int là 32 bit nhưng dài là 64 bit ở chế độ 64 bit.

MSVC chẳng hạn sử dụng mô hình LLP64, có nghĩa là cả int và long đều là 32 bit ngay cả ở chế độ 64 bit.


có thể là 0 byte? hmm
rogerdpack

12

Bản thân đặc tả C ++ (phiên bản cũ nhưng đủ tốt cho việc này) bỏ ngỏ điều này.

Có bốn kiểu số nguyên có dấu: ' signed char', ' short int', ' int' và ' long int'. Trong danh sách này, mỗi loại cung cấp ít nhất dung lượng lưu trữ bằng những loại đứng trước nó trong danh sách. Các int thuần túy có kích thước tự nhiên được đề xuất bởi kiến ​​trúc của môi trường thực thi *;

[Chú thích cuối trang: nghĩa là đủ lớn để chứa bất kỳ giá trị nào trong phạm vi INT_MIN và INT_MAX, như được xác định trong tiêu đề <climits>. --- cuối foonote]


7

Như Kevin Haines đã chỉ ra, int có kích thước tự nhiên do môi trường thực thi đề xuất, kích thước này phải vừa với INT_MIN và INT_MAX.

Tiêu chuẩn C89 nói rằng UINT_MAXít nhất phải là 2 ^ 16-1, USHRT_MAX2 ^ 16-1 và ULONG_MAX2 ^ 32-1. Điều đó làm cho số lượng bit ít nhất là 16 cho short và int, và 32 cho dài. Đối với char, nó tuyên bố rõ ràng rằng nó phải có ít nhất 8 bit ( CHAR_BIT). C ++ kế thừa các quy tắc đó cho tệp limit.h, vì vậy trong C ++ chúng ta có các yêu cầu cơ bản giống nhau đối với các giá trị đó. Tuy nhiên, bạn không nên lấy từ đó int có ít nhất 2 byte. Về mặt lý thuyết, char, int và long đều có thể là 1 byte, trong trường hợp đó CHAR_BITít nhất phải là 32. Chỉ cần nhớ rằng "byte" luôn là kích thước của char, vì vậy nếu char lớn hơn, một byte không chỉ là 8 bit bất kỳ. hơn.


Tôi không nghĩ rằng một bytekiểu dữ liệu tồn tại trong C ++. Nó không, phải không? Nếu nó có, và một bytecó thể có kích thước khác hơn 8 bit, nó hoàn toàn là ngu ngốc. Tại sao họ gọi nó là byte trừ khi nó hoàn toàn nhất thiết phải là 8 bit?
Alderath

6

Nó phụ thuộc vào trình biên dịch của bạn. Bạn được đảm bảo rằng giá trị dài ít nhất sẽ lớn bằng số nguyên, nhưng bạn không được đảm bảo rằng nó sẽ dài hơn nữa.


5

Đối với hầu hết các phần, số byte và phạm vi giá trị được xác định bởi kiến ​​trúc của CPU chứ không phải C ++. Tuy nhiên, C ++ đặt ra các yêu cầu tối thiểu, điều này đã giải thích đúng và Martin York chỉ mắc một vài lỗi.

Lý do tại sao bạn không thể sử dụng int và long thay thế cho nhau là vì chúng không phải lúc nào cũng có cùng độ dài. C được phát minh trên PDP-11 trong đó một byte có 8 bit, int là hai byte và có thể được xử lý trực tiếp bằng các lệnh phần cứng. Vì các lập trình viên C thường cần số học bốn byte, từ lâu đã được phát minh và nó là bốn byte, được xử lý bởi các hàm thư viện. Các máy khác có thông số kỹ thuật khác. Tiêu chuẩn C áp đặt một số yêu cầu tối thiểu.


5

Việc dựa vào việc triển khai các kích thước kiểu nguyên thủy của nhà cung cấp trình biên dịch SẼ quay lại ám ảnh bạn nếu bạn từng biên dịch mã của mình trên một kiến ​​trúc máy khác, hệ điều hành hoặc trình biên dịch của nhà cung cấp khác.

Hầu hết các nhà cung cấp trình biên dịch cung cấp một tệp tiêu đề xác định các kiểu nguyên thủy với kích thước kiểu hết hạn. Những kiểu nguyên thủy này nên được sử dụng khi mã có thể được chuyển sang một trình biên dịch khác (đọc là LUÔN LUÔN trong MỌI trường hợp). Ví dụ, hầu hết các trình biên dịch UNIX đều có int8_t uint8_t int16_t int32_t uint32_t. Microsoft có INT8 UINT8 INT16 UINT16 INT32 UINT32. Tôi thích Borland / CodeGear's int8 uint8 int16 uint16 int32 uint32 . Những tên này cũng nhắc nhở một chút về kích thước / phạm vi của giá trị dự định.

Trong nhiều năm, tôi đã sử dụng tên kiểu nguyên thủy rõ ràng của Borland và #includetệp tiêu đề C / C ++ sau đây (nguyên thủy.h) nhằm xác định các kiểu nguyên thủy rõ ràng với những tên này cho bất kỳ trình biên dịch C / C ++ nào (tệp tiêu đề này có thể không thực sự bao gồm mọi trình biên dịch nhưng nó bao gồm một số trình biên dịch mà tôi đã sử dụng trên Windows, UNIX và Linux, nó cũng không (chưa) xác định các loại 64bit).

#ifndef primitiveH
#define primitiveH
// Header file primitive.h
// Primitive types
// For C and/or C++
// This header file is intended to define a set of primitive types
// that will always be the same number bytes on any operating operating systems
// and/or for several popular C/C++ compiler vendors.
// Currently the type definitions cover:
// Windows (16 or 32 bit)
// Linux
// UNIX (HP/US, Solaris)
// And the following compiler vendors
// Microsoft, Borland/Imprise/CodeGear, SunStudio,  HP/UX
// (maybe GNU C/C++)
// This does not currently include 64bit primitives.
#define float64 double
#define float32 float
// Some old C++ compilers didn't have bool type
// If your compiler does not have bool then add   emulate_bool
// to your command line -D option or defined macros.
#ifdef emulate_bool
#   ifdef TVISION
#     define bool int
#     define true 1
#     define false 0
#   else
#     ifdef __BCPLUSPLUS__
      //BC++ bool type not available until 5.0
#        define BI_NO_BOOL
#        include <classlib/defs.h>
#     else
#        define bool int
#        define true 1
#        define false 0
#     endif
#  endif
#endif
#ifdef __BCPLUSPLUS__
#  include <systypes.h>
#else
#  ifdef unix
#     ifdef hpux
#        include <sys/_inttypes.h>
#     endif
#     ifdef sun
#        include <sys/int_types.h>
#     endif
#     ifdef linux
#        include <idna.h>
#     endif
#     define int8 int8_t
#     define uint8 uint8_t
#     define int16 int16_t
#     define int32 int32_t
#     define uint16 uint16_t
#     define uint32 uint32_t
#  else
#     ifdef  _MSC_VER
#        include <BaseTSD.h>
#        define int8 INT8
#        define uint8 UINT8
#        define int16 INT16
#        define int32 INT32
#        define uint16 UINT16
#        define uint32 UINT32
#     else
#        ifndef OWL6
//          OWL version 6 already defines these types
#           define int8 char
#           define uint8 unsigned char
#           ifdef __WIN32_
#              define int16 short int
#              define int32 long
#              define uint16 unsigned short int
#              define uint32 unsigned long
#           else
#              define int16 int
#              define int32 long
#              define uint16 unsigned int
#              define uint32 unsigned long
#           endif
#        endif
#      endif
#  endif
#endif
typedef int8   sint8;
typedef int16  sint16;
typedef int32  sint32;
typedef uint8  nat8;
typedef uint16 nat16;
typedef uint32 nat32;
typedef const char * cASCIIz;    // constant null terminated char array
typedef char *       ASCIIz;     // null terminated char array
#endif
//primitive.h

C99 quy định rằng các kiểu chữ trông như int32_t, uint64_t, v.v. được trình biên dịch xác định và có chính xác bao nhiêu bit như tên gợi ý. Hầu hết các trình biên dịch C ++ (bao gồm cả g ++) sẽ cho phép bạn sử dụng các hằng số này trong mã C ++.
rmeador

5

Các ++ Chuẩn C nói nó như thế này:

3.9.1, §2:

Có năm kiểu số nguyên có dấu: "char có dấu", "short int", "int", "long int" và "long long int". Trong danh sách này, mỗi loại cung cấp ít nhất dung lượng lưu trữ bằng những loại đứng trước nó trong danh sách. Các int thuần túy có kích thước tự nhiên được đề xuất bởi kiến ​​trúc của môi trường thực thi (44); các kiểu số nguyên có dấu khác được cung cấp để đáp ứng các nhu cầu đặc biệt.

(44) nghĩa là, đủ lớn để chứa bất kỳ giá trị nào trong phạm vi INT_MIN và INT_MAX, như được xác định trong tiêu đề <climits> .

Kết luận: nó phụ thuộc vào kiến ​​trúc bạn đang làm việc. Bất kỳ giả định nào khác là sai.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.