int และ long ใน C ++ ต่างกันอย่างไร


120

แก้ไขฉันถ้าฉันผิด

int คือ 4 ไบต์โดยมีช่วงของค่าตั้งแต่ -2,147,483,648 ถึง 2,147,483,647 (2 ^ 31)
long คือ 4 ไบต์โดยมีช่วงของค่าตั้งแต่ -2,147,483,648 ถึง 2,147,483,647 (2 ^ 31)

C ++ แตกต่างกันอย่างไร? สามารถใช้แทนกันได้หรือไม่?


ใน VS2005 ของฉันทำงานบนโปรเซสเซอร์ 32 บิตขนาดเริ่มต้นของ int คือ 4 ไบต์


หากคุณต้องการเขียนโค้ดแบบพกพาให้พิจารณาใช้#include <stdint.h>และประเภทที่บอกขนาด เช่นuint32_t. บนแพลตฟอร์มใหม่คุณจะต้องตรวจสอบให้แน่ใจว่า stdint.h ทำให้ถูกต้องสำหรับแพลตฟอร์มนั้น ๆ และโค้ดของคุณทำงานได้ตามที่ตั้งใจไว้
BitTickler

คำตอบ:


112

ขึ้นอยู่กับการใช้งาน

ตัวอย่างเช่นใน Windows จะเหมือนกัน แต่ตัวอย่างเช่นในระบบ Alpha ความยาวคือ 64 บิตในขณะที่ int คือ 32 บิต นี้บทความครอบคลุมกฎสำหรับ Intel C ++ คอมไพเลอร์บนแพลตฟอร์มตัวแปร สรุป:

  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  

ฉันคิดว่าเราควรพิจารณารวมคำตอบนี้ (คำตอบตามตัวอย่าง) กับรายละเอียดด้านล่างเกี่ยวกับมาตรฐาน C ++ แบบร่างสำหรับ C ++ 0x อยู่ที่open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2798.pdfและมีการมาร์กอัปเพื่อให้คุณเห็นความแตกต่างระหว่างมันกับรอบสุดท้าย
Patrick Johnmeyer

การรวมบางสิ่งบางอย่างตามลำดับที่ชาญฉลาดขนาดสัมพัทธ์ของประเภทจะให้ข้อมูลมากกว่าการแจกแจงขนาดสำหรับแพลตฟอร์มที่แตกต่างกันเช่นสถานะ @Kevin เป็นอย่างดี (-1vote)
xtofl

2
คอมไพเลอร์บางตัวมีแฟล็กที่อนุญาตให้คุณแก้ไขขนาดเริ่มต้นของ int และ long เช่นบังคับให้เป็น 8 หรือ 16 เป็นต้นดูรายละเอียดในเอกสารของคอมไพเลอร์
Martin York

7
โปรดทราบว่าเหล่านี้มีขนาดยาว
rogerdpack

1
โปรดระบุขนาดของ int ด้วย
cegprakash

82

การรับประกันเดียวที่คุณมีคือ:

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

ยังเห็น: คือlongการรับประกันว่าจะมีอย่างน้อย 32 บิต?


1
อืมนี่ไม่ถือถ้า sizeof (short)> = sizeof (char) เรารู้แค่ว่า sizeof (short)> = 1 (not> = 2) ซึ่ง btw ไปสำหรับทุกประเภท ตาม sizeof นี้ (อินทิกรัลชนิดใดก็ได้)> = 1 ซึ่งเป็นความจริงเช่นฉันจำ sizeof (int) == 1 บน Z80 ได้ แต่ไม่มีการรับประกันที่ดีกว่าสำหรับระยะยาว?
Andreas Magnusson

6
3.9.1.2 ของมาตรฐาน C ++ ระบุว่า sizeof (long)> = sizeof (int)> = sizeof (short)> = sizeof (ถ่าน) 5.3.3.1 ของมาตรฐาน C ++ ระบุขนาดนั้น (ถ่าน), sizeof (ถ่านที่ไม่ได้ลงชื่อ) และ sizeof (ลงนามถ่าน) เท่ากับ 1 (ต่อ ... )
เคทีซี

4
(... ต่อ) ค่าสูงสุดและค่าต่ำสุดที่แสดงโดยชนิดอินทิกรัลถูกกำหนดให้เป็นมาโครใน <LIMIT.h> (และด้วยเหตุนี้ <climits>) ภาคผนวก E ของมาตรฐาน C (1990) ซึ่งรวมไว้โดยการอ้างอิงจากมาตรฐาน C ++ ระบุขนาดขั้นต่ำของมาโครเหล่านี้ (ต่อ ... )
เคทีซี

4
(... ต่อ) และพวกเขาคือ (2 ^ 15) -1, (2 ^ 15) -1, (2 ^ 31) -1 สำหรับ short, int และ long ตามลำดับซึ่งได้ผลเป็นค่าเป็น โพสต์โดย Martin York ในคำตอบของเขาที่นี่หาก CHAR_BIT คือ 8 (ซึ่งเป็นค่าต่ำสุดด้วย)
เคทีซี

2
@ ไจลส์: นั่นไม่ใช่สิ่งที่ฉันกล่าวไว้ข้างต้นใช่หรือไม่? sizeof (short) * CHAR_BITS> = 16. ใส่สิ่งอื่น ๆ :-)
Martin York

13

เมื่อคอมไพล์สำหรับ x64 ความแตกต่างระหว่าง int และ long จะอยู่ระหว่าง 0 ถึง 4 ไบต์ขึ้นอยู่กับคอมไพเลอร์ที่คุณใช้

GCC ใช้โมเดล LP64 ซึ่งหมายความว่า ints เป็น 32 บิต แต่ longs เป็น 64 บิตภายใต้โหมด 64 บิต

ตัวอย่างเช่น MSVC ใช้โมเดล LLP64 ซึ่งหมายความว่าทั้ง ints และ longs เป็น 32 บิตแม้ในโหมด 64 บิต


อาจเป็น 0 ไบต์? อืม
rogerdpack

12

ข้อกำหนดC ++ เอง (รุ่นเก่า แต่ดีพอสำหรับสิ่งนี้) ปล่อยให้สิ่งนี้เปิดอยู่

ประเภทจำนวนเต็มลงนามมีสี่ประเภท: ' signed char', ' short int', ' int' และ ' long int' ในรายการนี้แต่ละประเภทมีพื้นที่จัดเก็บอย่างน้อยที่สุดเท่าที่มีอยู่ก่อนหน้าในรายการ ints ธรรมดามีขนาดตามธรรมชาติที่แนะนำโดยสถาปัตยกรรมของสภาพแวดล้อมการดำเนินการ *;

[เชิงอรรถ: นั่นคือขนาดใหญ่พอที่จะมีค่าใด ๆ ในช่วงของ INT_MIN และ INT_MAX <climits>ที่กำหนดไว้ในส่วนหัว - ท้าย foonote]


7

ดังที่ Kevin Haines ชี้ให้เห็นว่า ints มีขนาดตามธรรมชาติที่แนะนำโดยสภาพแวดล้อมการดำเนินการซึ่งต้องพอดีกับ INT_MIN และ INT_MAX

มาตรฐาน C89 ระบุว่าUINT_MAXควรมีค่าอย่างน้อย 2 ^ 16-1, USHRT_MAX2 ^ 16-1 และULONG_MAX2 ^ 32-1 นั่นทำให้บิตนับเป็นอย่างน้อย 16 สำหรับ short และ int และ 32 สำหรับ long สำหรับถ่านจะระบุอย่างชัดเจนว่าควรมีอย่างน้อย 8 บิต ( CHAR_BIT) C ++ สืบทอดกฎเหล่านั้นสำหรับไฟล์ limit.h ดังนั้นใน C ++ เราจึงมีข้อกำหนดพื้นฐานเดียวกันสำหรับค่าเหล่านั้น อย่างไรก็ตามคุณไม่ควรได้รับจาก int นั้นอย่างน้อย 2 ไบต์ ตามทฤษฎีแล้ว char, int และ long อาจเป็น 1 ไบต์ซึ่งในกรณีนี้CHAR_BITต้องมีอย่างน้อย 32 โปรดจำไว้ว่า "byte" จะมีขนาดเท่ากับ char เสมอดังนั้นหาก char มีขนาดใหญ่ขึ้นไบต์จะไม่เพียง 8 บิตเท่านั้น มากกว่า.


ฉันไม่คิดว่ามีbyteประเภทข้อมูลอยู่ใน C ++ มันไม่ได้หรือ ถ้าเป็นเช่นนั้นและbyteกระป๋องมีขนาดอื่นที่ไม่ใช่ 8 บิตมันก็โง่ล้วนๆ ทำไมพวกเขาถึงเรียกมันว่าไบต์เว้นแต่ว่ามันจะเป็น 8 บิต?
Alderath

6

ขึ้นอยู่กับคอมไพเลอร์ของคุณ คุณรับประกันได้ว่า long อย่างน้อยจะมีขนาดใหญ่เท่ากับ int แต่คุณไม่รับประกันว่าจะยาวอีกต่อไป


5

โดยส่วนใหญ่จำนวนไบต์และช่วงของค่าจะถูกกำหนดโดยสถาปัตยกรรมของ CPU ไม่ใช่ C ++ อย่างไรก็ตาม C ++ กำหนดข้อกำหนดขั้นต่ำซึ่ง litb อธิบายอย่างถูกต้องและ Martin York ทำผิดพลาดเพียงเล็กน้อยเท่านั้น

สาเหตุที่คุณไม่สามารถใช้ int และ long แทนกันได้เนื่องจากความยาวไม่เท่ากันเสมอไป C ถูกประดิษฐ์ขึ้นบน PDP-11 โดยที่ไบต์มี 8 บิต int เป็นสองไบต์และสามารถจัดการได้โดยตรงโดยคำสั่งฮาร์ดแวร์ เนื่องจากโปรแกรมเมอร์ C มักต้องการเลขคณิตสี่ไบต์จึงมีการคิดค้นมานานและมีขนาดสี่ไบต์ซึ่งจัดการโดยฟังก์ชันไลบรารี เครื่องอื่น ๆ มีคุณสมบัติที่แตกต่างกัน มาตรฐาน C กำหนดข้อกำหนดขั้นต่ำบางประการ


5

การอาศัยการใช้งานขนาดประเภทดั้งเดิมของผู้จำหน่ายคอมไพเลอร์จะกลับมาหลอกหลอนคุณหากคุณเคยคอมไพล์โค้ดของคุณบนสถาปัตยกรรมเครื่องอื่นระบบปฏิบัติการหรือคอมไพเลอร์ของผู้ขายรายอื่น

ผู้จำหน่ายคอมไพเลอร์ส่วนใหญ่จัดเตรียมไฟล์ส่วนหัวที่กำหนดชนิดพื้นฐานที่มีขนาดประเภทการระเบิด ควรใช้ประเภทดั้งเดิมเหล่านี้เมื่อโค้ดอาจถูกย้ายไปยังคอมไพเลอร์อื่น (อ่านว่าเสมอในทุกอินสแตนซ์) ตัวอย่างเช่นคอมไพเลอร์ UNIX ส่วนใหญ่มีint8_t uint8_t int16_t int32_t uint32_t. Microsoft มีINT8 UINT8 INT16 UINT16 INT32 UINT32. ฉันชอบ int8 uint8 int16 uint16 int32 uint32Borland ชื่อเหล่านี้ยังช่วยเตือนขนาด / ช่วงของค่าที่ต้องการ

เป็นเวลาหลายปีแล้วที่ฉันใช้ชื่อชนิดดั้งเดิมที่ชัดเจนของ Borland และ#includeไฟล์ส่วนหัว C / C ++ ต่อไปนี้ (primitive.h) ซึ่งมีจุดมุ่งหมายเพื่อกำหนดประเภทดั้งเดิมที่ชัดเจนด้วยชื่อเหล่านี้สำหรับคอมไพเลอร์ C / C ++ (ไฟล์ส่วนหัวนี้อาจไม่ครอบคลุมทุก คอมไพเลอร์ แต่ครอบคลุมคอมไพเลอร์หลายตัวที่ฉันใช้บน Windows, UNIX และ Linux แต่ยังไม่ (ยัง) กำหนดประเภท 64 บิต)

#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 กำหนดให้ typdef ที่มีลักษณะเหมือน int32_t, uint64_t ฯลฯ ถูกกำหนดโดยคอมไพเลอร์และมีบิตมากเท่าที่ชื่อแนะนำ คอมไพเลอร์ C ++ ส่วนใหญ่ (รวมถึง g ++) จะอนุญาตให้คุณใช้ค่าคงที่เหล่านี้ในโค้ด C ++
rmeador

5

c ++ มาตรฐานกล่าวเช่นนี้

3.9.1, §2:

ประเภทจำนวนเต็มที่ลงนามมีอยู่ 5 ประเภท ได้แก่ "signed char" "short int" "int" "long int" และ "long long int" ในรายการนี้แต่ละประเภทมีพื้นที่จัดเก็บอย่างน้อยที่สุดเท่าที่มีอยู่ก่อนหน้าในรายการ ints ธรรมดามีขนาดตามธรรมชาติที่แนะนำโดยสถาปัตยกรรมของสภาพแวดล้อมการดำเนินการ (44); ประเภทจำนวนเต็มลงนามอื่น ๆ มีไว้เพื่อตอบสนองความต้องการพิเศษ

(44) นั่นคือขนาดใหญ่พอที่จะมีค่าใด ๆ ในช่วงของ INT_MIN และ INT_MAX <climits>ที่กำหนดไว้ในส่วนหัว

ข้อสรุป: ขึ้นอยู่กับสถาปัตยกรรมที่คุณกำลังทำงานอยู่ ข้อสันนิษฐานอื่นใดเป็นเท็จ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.