มาตรฐาน C ++ ระบุขนาดของ int, long type ที่จะเป็นอย่างไร


696

ฉันกำลังมองหาข้อมูลโดยละเอียดเกี่ยวกับขนาดของประเภท C ++ พื้นฐาน ฉันรู้ว่ามันขึ้นอยู่กับสถาปัตยกรรม (16 บิต, 32 บิต, 64 บิต) และคอมไพเลอร์

แต่มีมาตรฐานสำหรับ C ++ หรือไม่

ฉันใช้ Visual Studio 2008 บนสถาปัตยกรรม 32 บิต นี่คือสิ่งที่ฉันได้รับ:

char  : 1 byte
short : 2 bytes
int   : 4 bytes
long  : 4 bytes
float : 4 bytes
double: 8 bytes

ฉันพยายามที่จะหาไม่ประสบความสำเร็จมากข้อมูลที่เชื่อถือได้ระบุขนาดของchar, short, int, long, double, float(และประเภทอื่น ๆ ผมไม่ได้คิดว่า) ภายใต้สถาปัตยกรรมที่แตกต่างกันและคอมไพเลอร์


18
@ มันยากที่จะไม่เลือก ... มีสถาปัตยกรรมจำนวนมากที่จะสนับสนุนว่ามันจะต้องมีความยืดหยุ่น
Krakkos


4
เหตุใดพวกเขาจึงไม่ลบประเภทที่คลุมเครือทั้งหมดและสร้างมาตรฐานให้เป็นประเภทความยาวบิตที่แน่นอนเช่น int32_t, uint32_t, int64_t เป็นต้น
developerbmw

5
@thyrgle มันค่อนข้างยากที่จะสร้างมาตรฐานแบบนี้ แตกต่างจาก Java ซึ่งสิ่งเหล่านี้คงที่เพราะวิธีการทำงานของ JVM, C / C ++ เป็นหลักต้องติดกับระบบที่พวกเขาวิ่งไปโดยไม่มีเลเยอร์นามธรรมแฟนซี (อย่างน้อยไม่มากเท่ากับ Java) ระหว่าง. หากขนาดของ int เป็นสิ่งสำคัญสิ่งหนึ่งที่สามารถใช้งานint16_tได้int32_tและint64_t(ต้องมีการiostreamรวมไว้เพื่อถ้าฉันจำได้อย่างถูกต้อง) มีอะไรดีเกี่ยวกับเรื่องนี้ที่ int64_t ไม่ควรมีปัญหาในระบบ 32 บิต (ซึ่งจะส่งผลกระทบต่อประสิทธิภาพการทำงาน)
rbaleksandar

5
@rbaleksandar พวกเขากำลังที่กำหนดไว้จริงในไม่<cstdint> <iostream>
Justin Time - Reinstate Monica

คำตอบ:


685

มาตรฐาน C ++ ไม่ได้ระบุขนาดของชนิดอินทิกรัลเป็นไบต์ แต่ระบุช่วงต่ำสุดที่จะต้องสามารถเก็บได้ คุณสามารถอนุมานขนาดขั้นต่ำเป็นบิตจากช่วงที่ต้องการ คุณสามารถอนุมานขนาดต่ำสุดในไบต์จากที่และค่าของCHAR_BITแมโครที่กำหนดจำนวนบิตในไบต์ ทั้งหมดยกเว้นแพลตฟอร์มที่คลุมเครือมากที่สุดคือ 8 และต้องไม่น้อยกว่า 8 นั่นเป็นเพราะมันต้องมีขนาดใหญ่พอที่จะเก็บ "หน่วยรหัสแปดบิตของรูปแบบการเข้ารหัส Unicode UTF-8"

ข้อ จำกัด เพิ่มเติมอย่างหนึ่งcharคือขนาดของมันคือ 1 ไบต์หรือCHAR_BITบิตเสมอ (ดังนั้นชื่อ) นี่คือที่ระบุไว้อย่างชัดเจนในมาตรฐาน

มาตรฐาน C เป็นการอ้างอิงเชิงบรรทัดฐานสำหรับมาตรฐาน C ++ ดังนั้นแม้ว่าจะไม่ได้ระบุข้อกำหนดเหล่านี้อย่างชัดเจนก็ตาม C ++ ต้องการช่วงต่ำสุดที่มาตรฐาน C กำหนด (หน้า 22) ซึ่งเหมือนกับช่วงจากประเภทข้อมูลในMSDN :

  1. signed char: -127 ถึง 127 (หมายเหตุไม่ใช่ -128 ถึง 127 ซึ่งรองรับแพลตฟอร์ม 1's-complement และ sign-and-magnitude)
  2. unsigned char: 0 ถึง 255
  3. "ธรรมดา" char: ช่วงเดียวกับsigned charหรือunsigned char, การดำเนินงานที่กำหนดไว้
  4. signed short: -32767 ถึง 32767
  5. unsigned short: 0 ถึง 65535
  6. signed int: -32767 ถึง 32767
  7. unsigned int: 0 ถึง 65535
  8. signed long: -2147483647 ถึง 2147483647
  9. unsigned long: 0 ถึง 4294967295
  10. signed long long: -9223372036854775807 ถึง 9223372036854775807
  11. unsigned long long: 0 ถึง 18446744073709551615

การใช้งาน C ++ (หรือ C) สามารถกำหนดขนาดของชนิดเป็นไบต์sizeof(type)ให้เป็นค่าใดก็ได้ตราบใดที่

  1. นิพจน์sizeof(type) * CHAR_BITจะประเมินเป็นจำนวนบิตสูงพอที่จะมีช่วงที่ต้องการและ
  2. การเรียงลำดับประเภทยังคงใช้ได้ (เช่นsizeof(int) <= sizeof(long))

การนำสิ่งนี้มารวมกันเรารับประกันได้ว่า:

  • char, signed charและunsigned charอย่างน้อย 8 บิต
  • signed short, unsigned short, signed intและunsigned intอย่างน้อย 16 บิต
  • signed longและunsigned longมีอย่างน้อย 32 บิต
  • signed long longและunsigned long longมีอย่างน้อย 64 บิต

ไม่มีการรับประกันจะทำเกี่ยวกับขนาดของfloatหรือdoubleยกเว้นว่าให้อย่างน้อยเป็นความแม่นยำมากที่สุดเท่าที่doublefloat

ช่วงเฉพาะของการนำไปใช้งานจริงสามารถพบได้ใน<limits.h>ส่วนหัวใน C หรือ<climits>ใน C ++ (หรือดีกว่า templated std::numeric_limitsใน<limits>ส่วนหัว)

ตัวอย่างเช่นนี่คือวิธีที่คุณจะพบช่วงสูงสุดสำหรับint:

ค:

#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;

C ++ :

#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();

49
แต่มาตรฐาน C ++ ใช้คำว่าไบต์เพื่อหมายถึง "1 char" ไม่ใช่ความหมายปกติ
Ben Voigt

4
@Programmer อ่านคำตอบ (จุดที่ 1 หมายเหตุในวงเล็บ) หรือถ้อยคำมาตรฐานที่แท้จริง (เชื่อมโยงในคำตอบ) มาตรฐาน C รองรับสถาปัตยกรรมประกอบของ 1 ซึ่งมีการแสดงที่แตกต่างจากส่วนประกอบ 2 ที่แพร่หลายที่สุด ช่วงการรับประกันขั้นต่ำจะแตกต่างจากช่วงที่ใช้งานจริง
อเล็กซ์ B

9
@Alex B คุณไม่ได้พูดอะไรเกี่ยวกับคำตอบของคุณเป็นสองเท่า คุณช่วยอัพเดทคำตอบสำหรับตัวแปรทศนิยมได้ไหม?
Cool_Coder

3
@Cool_Coder: จุดลอยตัวเป็นปลากาต้มน้ำเพิ่มเติมทั้งหมดได้อย่างง่ายดายสองเท่าขนาดโพสต์
Deduplicator

3
@Mooing Duck: "ทุกเวอร์ชั่นของ C ++ ต้องการ 256 ค่าที่แตกต่าง [สำหรับประเภท char ที่เซ็นชื่อ]" ไม่นั่นไม่เป็นความจริงจนกว่าจะได้รับการแก้ไขในรายละเอียด C ++ ล่าสุด ข้อกำหนดที่เก่ากว่าอนุญาตประเภทถ่านที่ลงนามแล้วให้มีรูปแบบบิตที่ไม่ได้จับคู่กับตัวเลขดังนั้นพวกเขาจึงขาดข้อกำหนดที่มีค่า 256 ที่แตกต่าง "สำหรับประเภทอักขระที่ไม่ได้ลงชื่อรูปแบบบิตที่เป็นไปได้ทั้งหมดของการแทนค่าแสดงถึงตัวเลขข้อกำหนดเหล่านี้ไม่ได้เก็บไว้สำหรับประเภทอื่น"
Adrian McCarthy

241

สำหรับระบบ 32 บิตมาตรฐาน 'พฤตินัย' เป็น ILP32 - นั่นคือint, longและตัวชี้มีทั้งหมดจำนวน 32 บิต

สำหรับระบบ 64 บิตมาตรฐาน Unix 'de พฤตินัย' หลักคือ LP64 - longและตัวชี้เป็น 64- บิต (แต่intเป็น 32- บิต) มาตรฐาน Windows 64 บิตคือ LLP64 - long longและตัวชี้เป็น 64- บิต (แต่longและintทั้งคู่เป็น 32- บิต)

ครั้งหนึ่งระบบ Unix บางระบบใช้ ILP64 Organization

มาตรฐานเหล่านี้ไม่ได้ถูกควบคุมโดยมาตรฐาน C (ISO / IEC 9899: 1999) แต่ทั้งหมดได้รับอนุญาตจากมัน

และตามคำนิยามsizeof(char)คือ1แม้จะมีการทดสอบในสคริปต์กำหนดค่า Perl

โปรดทราบว่ามีเครื่องจักร (Crays) ซึ่งCHAR_BITมีขนาดใหญ่กว่า 8 นั่นหมายถึง IIRC นั่นsizeof(int)ก็คือ 1 เพราะทั้งคู่charและint32- บิต


73
+1 สำหรับการระบุว่าสิ่งต่าง ๆ จริง ๆ ในกรณีที่สำคัญที่สุดมากกว่าในทฤษฎี ถ้าคุณต้องการใช้ 32 บิต int ถ้าคุณต้องการ 64 บิตใช้นานนาน ถ้าคุณต้องการใช้เนทิฟ size_t หลีกเลี่ยง "ธรรมดา" ที่ยาวเพราะมันแตกต่างกันไป ควรใช้กับแอปพลิเคชั่นส่วนใหญ่
Eloff

37
+1 สำหรับคำตอบ @Eloff: ตรงกันข้าม ... หากคุณต้องการใช้ 32 บิต[u]int32_tหรือคล้ายกันถ้าคุณต้องการใช้ 64 บิต[u]int64_t... หากคุณไม่มีส่วนหัวให้ดาวน์โหลดหรือสร้างให้ดีกว่าโดยเลือกเวลาในการคอมไพล์ ประเภทดังกล่าวหรือการยืนยันแบบคงที่เพื่อตรวจสอบขนาด pubs.opengroup.org/onlinepubs/009695299/basedefs/stdint.h.html หากขนาดที่แม่นยำไม่สำคัญนักและคุณสนใจเพียงอย่างน้อยก็ใหญ่คำแนะนำของคุณก็คือแพลตฟอร์มพีซี / เซิร์ฟเวอร์ทั่วไปที่ทันสมัย
Tony Delroy

8
โปรดทราบว่ามันไม่ได้เป็นเพียงแค่เครื่อง Cray เก่าที่มี CHAR_BIT> 8. เช่นประมวลสัญญาณระบบมักจะมี CHAR_BIT 16 หรือ 32 (ดูเช่นเหล่านี้ )
เลขที่

2
@nos: ขอบคุณสำหรับลิงค์ มันจะมีประโยชน์มากหากมีระบบที่ทันสมัยและเป็นปัจจุบันซึ่งถูกระบุไว้สำหรับคดีคี่บอล จากความอยากรู้สิ่งที่รหัสตั้งอยู่บนเครื่องเหล่านั้นคืออะไร? หากชุดรหัสคือ UTF-16 ดังนั้น 0xFFFF ไม่ใช่ตัวอักษรที่ถูกต้องและหากชุดรหัสเป็นชุดรหัส ISO 8859-x ดังนั้น 0xFFFF อีกครั้งจะไม่ใช่อักขระที่ถูกต้อง (รหัสอักขระจาก 0x00 ถึง 0xFF) ฉันยังไม่เชื่อว่ามีปัญหาการตรวจสอบ EOF แต่มีแน่นอนห้องพักสำหรับความระมัดระวังและอาจจะสำหรับการเขียนและการใช้ฟังก์ชั่นint get_char(FILE *fp, char *c)ซึ่งจะส่งกลับ EOF หรือ 0 *cและชุด
Jonathan Leffler

2
@joelw: C11 ต้องการให้กำหนดuint32_t x=1,y=2;ค่าx-yต้องเป็น 4294967295 บนแพลตฟอร์มที่ "int" เป็น 32 บิตหรือเล็กกว่าและ -1 บนแพลตฟอร์มที่ "int" เป็น 33 บิตหรือใหญ่กว่า ยิ่งไปกว่านั้นมันจำเป็นx*yต้องได้รับการประเมินโดยใช้โมดูลาร์เลขคณิตสำหรับค่าทั้งหมดของ x และ y ถ้า "int" คือ 32 บิตหรือเล็กกว่าและเลขคณิตทั่วไปถ้า 65 บิตหรือใหญ่กว่า แต่ไม่มีข้อกำหนดใด ๆ กับสิ่งที่อาจเกิดขึ้นกับค่าขนาดใหญ่ ของ x และ y ถ้า "int" คือ 33 ถึง 64 บิต
supercat

88

ในทางปฏิบัติไม่มีสิ่งนั้น บ่อยครั้งที่คุณสามารถคาดหวังว่าstd::size_tจะเป็นตัวแทนของขนาดจำนวนเต็มพื้นเมืองที่ไม่ได้ลงนามในสถาปัตยกรรมปัจจุบัน เช่น 16 บิต, 32- บิตหรือ 64- บิต แต่มันก็ไม่ได้เป็นกรณีที่ชี้ให้เห็นในความคิดเห็นต่อคำตอบนี้

เท่าที่ประเภทอื่น ๆ ในตัวไปมันขึ้นอยู่กับคอมไพเลอร์ นี่คือข้อความที่ตัดตอนมาสองข้อที่นำมาจากร่างการทำงานปัจจุบันของมาตรฐาน C ++ ล่าสุด:

มีจำนวนเต็มเซ็นชื่อมาตรฐานห้าประเภท: char ที่ลงนามแล้ว, int สั้น, int, long int และ long long int ในรายการนี้แต่ละประเภทมีพื้นที่เก็บข้อมูลอย่างน้อยเท่ากับพื้นที่นำหน้าในรายการ

สำหรับประเภทเลขจำนวนเต็มมาตรฐานที่ลงนามแล้วมีประเภทจำนวนเต็มมาตรฐานที่ไม่ได้ลงนาม (แต่แตกต่างกัน): ถ่านที่ไม่ได้ลงนาม, char ที่ไม่ได้ลงชื่อ, int ที่ไม่ได้ลงนาม, int ที่ไม่ได้ลงชื่อ, int ยาวที่ไม่ได้ลงชื่อ การจัดเก็บและมีความต้องการการจัดตำแหน่งเดียวกัน

หากคุณต้องการให้คุณสามารถคงที่ (รวบรวมเวลา) ยืนยันขนาดของประเภทพื้นฐานเหล่านี้ มันจะเตือนผู้คนให้นึกถึงการเปลี่ยนรหัสของคุณหากขนาดของสมมติฐานเปลี่ยนไป


7
โพสต์ที่ดี สิ่งอื่นที่จำเป็นต้องมีคือขนาดบิตที่น้อยที่สุดต่อไปนี้ (บันทึกไว้ใน c89 / c99 พร้อมกับขีด จำกัด h และยึดครองโดย c ++): char> = 8, short และ int> = 16, long> = 32
Johannes Schaub - litb

1
นอกจากนี้บนแพลตฟอร์มขนาด 8 บิต AVR size_t จะไม่เป็น 8 บิต แต่เป็น 16 เพราะตัวชี้และขนาด int เป็น 16 บิต ดังนั้นขนาดข้อมูลดั้งเดิมของโปรเซสเซอร์จึงไม่เกี่ยวข้องกับ size_t
Robotbugs

80

มีมาตรฐาน

มาตรฐาน C90 นั้นต้องการ

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

มาตรฐาน C99 นั้นต้องการสิ่งนั้น

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

นี่คือข้อกำหนด C99นี่คือรายละเอียดขนาดรายละเอียดของอินทิกรัลต่างประเภท

นี่คือขนาด int ประเภท (บิต) สำหรับแพลตฟอร์ม Windows:

Type           C99 Minimum     Windows 32bit
char           8               8
short          16              16
int            16              32
long           32              32
long long      64              64

หากคุณกังวลเกี่ยวกับการพกพาหรือคุณต้องการชื่อประเภทที่สะท้อนขนาดคุณสามารถดูส่วนหัว<inttypes.h>ที่มีมาโครต่อไปนี้:

int8_t
int16_t
int32_t
int64_t

int8_tรับประกันว่าจะเป็น 8 บิตและint16_tรับประกันเป็น 16 บิต ฯลฯ


8
มาตรฐาน nitpick: มาตรฐานพูดว่าsizeof(long) < sizeof(long long)ตรงข้ามกับสมมาตรsizeof(long) <= sizeof(long long)ที่ไหน?
Jonathan Leffler

2
@JonathonLeffler - ดู C99 5.2.4.2.1 - ขนาดของประเภทจำนวนเต็ม minsizeof (int) == 16-bits, minsizeof (long) == 32-bits, minsizeof (long) == 64- บิต ดังนั้นฉันคิดว่าคุณพูดถูก <= เนื่องจากไม่มีการระบุขนาดสูงสุด (ประเภท)
Jesse Chisholm

ขนาดคล้ายกัน (ลอย) <= sizeof (สองครั้ง) <= sizeof (ยาวคู่) ตาม C99 7.12 วรรค 2
Jesse Chisholm

38

หากคุณจำเป็นต้องได้รับการแก้ไขประเภทขนาดการใช้งานประเภทเช่น uint32_t (จำนวนเต็มไม่ได้ลงนาม 32 บิต) ที่กำหนดไว้ในstdint.h พวกเขาจะระบุไว้ในC99


10
มีการระบุ แต่ไม่จำเป็น
dreamlax

2
@dreamlax แพลตฟอร์มใดที่ไม่รวมไว้
Levi Morrison

3
@LeviMorrison: แพลตฟอร์มใด ๆ ที่ไม่มีในรูปแบบที่ต้องการ แพลตฟอร์มที่มีตัวอย่างเช่นจะไม่ได้มีCHAR_BIT == 16 int8_tแพลตฟอร์มใด ๆ ที่ไม่ได้ใช้งานส่วนประกอบสองตัวจะไม่มีส่วนใด ๆของพวกเขา (เนื่องจากส่วนเสริมทั้งสองนั้นจำเป็นต้องมีตามมาตรฐาน)
DevSolar

36

อัปเดต: C ++ 11 นำประเภทจาก TR1 เข้าสู่มาตรฐานอย่างเป็นทางการ:

  • int ยาวนาน
  • int long long ที่ไม่ได้ลงชื่อ

และประเภท "ขนาด" จาก <cstdint>

  • int8_t
  • int16_t
  • int32_t
  • int64_t
  • (และคู่หูที่ไม่ได้ลงชื่อ)

รวมทั้งคุณจะได้รับ:

  • int_least8_t
  • int_least16_t
  • int_least32_t
  • int_least64_t
  • บวกคู่ที่ไม่ได้ลงนาม

ประเภทเหล่านี้เป็นตัวแทนประเภทจำนวนเต็มน้อยที่สุดที่มีจำนวนบิตอย่างน้อยตามที่ระบุ ในทำนองเดียวกันมีจำนวนเต็ม "เร็วที่สุด" ที่มีจำนวนบิตอย่างน้อยที่ระบุ:

  • int_fast8_t
  • int_fast16_t
  • int_fast32_t
  • int_fast64_t
  • รวมทั้งรุ่นที่ไม่ได้ลงนาม

"เร็ว" หมายถึงอะไรถ้ามีอะไรขึ้นอยู่กับการนำไปใช้ ไม่จำเป็นต้องเร็วที่สุดสำหรับทุกวัตถุประสงค์เช่นกัน


นี่เป็นส่วนหนึ่งของมาตรฐาน C ++ 11 ในขณะนี้
Jaan

2
"เร็ว" หมายถึงปรับแต่งให้เข้ากับสถาปัตยกรรมฮาร์ดแวร์ หากรีจิสเตอร์เป็น 16 บิต int_fast8_t จะเป็นค่า 16 บิต หากการลงทะเบียนเป็น 32- บิตแล้ว int_fast8_t และ int_fast16_t เป็นค่าทั้ง 32 บิต ฯลฯ ดูหมวด C99 7.18.1.3 วรรค 2
Jesse Chisholm

19

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

3.9.1, §2:

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

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

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


12

ไม่ไม่มีขนาดมาตรฐานสำหรับประเภท มาตรฐานกำหนดว่า:

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

สิ่งที่ดีที่สุดที่คุณสามารถทำได้หากคุณต้องการตัวแปรที่มีขนาดคงที่คือใช้แมโครดังนี้:

#ifdef SYSTEM_X
  #define WORD int
#else
  #define WORD long int
#endif

จากนั้นคุณสามารถใช้ WORD เพื่อกำหนดตัวแปรของคุณ ไม่ใช่ว่าฉันชอบสิ่งนี้ แต่เป็นวิธีพกพาที่สุด


4
ปัญหาคือ WORD แพร่กระจายไปทั่วโปรแกรมในพื้นที่ที่ไม่ได้ขึ้นอยู่กับขนาดคงที่อย่างแท้จริง (ดูรหัส windows บางอัน) อย่างที่ฉันทราบเมื่อย้ายจากระบบ 16 บิตเป็น 32 บิตคุณจะพบปัญหาเดียวกันกับที่ WORD ตั้งใจจะแก้ปัญหา
lilburne

@liburne แน่นอนคุณควรใช้ WORD เฉพาะเมื่อคุณต้องการตัวแปรขนาดคงที่เช่นเมื่อคุณกำลังอ่าน / เขียนจาก / ไปยังไฟล์ หากส่วนหนึ่งของรหัสไม่ได้ขึ้นอยู่กับขนาดที่แน่นอนคุณควรใช้ตัวแปร "int" ตามปกติ
Emiliano

3
สิ่งที่ดีที่สุดที่คุณสามารถทำได้เพื่อให้ได้ขนาดพกพาควรเป็น#include <boost/cstdint.hpp>
kizzx2

11

เราได้รับอนุญาตให้กำหนดคำพ้องความหมายสำหรับประเภทเพื่อให้เราสามารถสร้าง "มาตรฐาน" ของเราเอง

บนเครื่องที่ sizeof (int) == 4 เราสามารถกำหนด:

typedef int int32;

int32 i;
int32 j;
...

ดังนั้นเมื่อเราถ่ายโอนรหัสไปยังเครื่องอื่นที่ขนาดจริงของ long int คือ 4 เราก็สามารถนิยามการเกิดขึ้นครั้งเดียวของ int ได้

typedef long int int32;

int32 i;
int32 j;
...

1
ไม่จำเป็นเนื่องจากส่วนหัวมาตรฐาน<stdint.h>(C99 ขึ้นไปและมาตรฐาน C ++ ใดก็ได้ที่ใช้เวอร์ชัน C99 ของไลบรารี C)
Keith Thompson

8

สำหรับเลขทศนิยมมีมาตรฐาน (IEEE754) : ลอยเป็น 32 บิตและคู่เป็น 64 นี่คือมาตรฐานฮาร์ดแวร์ไม่ใช่มาตรฐาน C ++ ดังนั้นคอมไพเลอร์สามารถกำหนดทฤษฏีและเพิ่มเป็นสองเท่าสำหรับขนาดอื่น ๆ แต่ในทางปฏิบัติฉัน ' ไม่เคยเห็นสถาปัตยกรรมที่ใช้อะไรที่แตกต่างออกไป


2
อย่างไรก็ตามการปฏิบัติตามมาตรฐาน IEEE 754 (aka IEC 559) เป็นทางเลือกภายใน C ++ (อาจเป็น C เช่นกัน แต่ฉันไม่แน่ใจ) ดู std :: numeric_limits :: is_iec559
Drew Hall

1
จากนั้นคุณไม่เห็นคอมไพเลอร์ของ TI สำหรับ TMS320C28xx DSP ที่doubleมีขนาดเท่ากันfloat(และintเหมือนกับcharทั้งสองคือ 16 บิต) แต่พวกเขามี 64 long doubleบิต
starblue

7

มีมาตรฐานและระบุไว้ในเอกสารมาตรฐานต่าง ๆ (ISO, ANSI และ whatnot)

Wikipedia มีหน้าที่ยอดเยี่ยมที่อธิบายถึงประเภทต่างๆและจำนวนสูงสุดที่พวกเขาเก็บ: จำนวนเต็มในสาขาวิทยาศาสตร์คอมพิวเตอร์

อย่างไรก็ตามถึงแม้จะมีคอมไพเลอร์ C ++ มาตรฐานคุณสามารถค้นหาได้อย่างง่ายดายโดยใช้โค้ดต่อไปนี้:

#include <iostream>
#include <limits>


int main() {
    // Change the template parameter to the various different types.
    std::cout << std::numeric_limits<int>::max() << std::endl;
}

เอกสารสำหรับstd :: numeric_limitsสามารถดูได้ที่Roguewave Roguewaveมันมีคำสั่งอื่น ๆ มากมายที่คุณสามารถโทรหาเพื่อหาข้อ จำกัด ต่างๆ สิ่งนี้สามารถใช้กับชนิดใดก็ได้ที่บ่งบอกขนาดเช่น std :: streamsize

คำตอบของ John มีคำอธิบายที่ดีที่สุดเนื่องจากรับประกันได้ว่าจะเก็บไว้ ไม่ว่าคุณจะอยู่บนแพลตฟอร์มใดมีหน้าดีๆอีกหนึ่งรายการที่มีรายละเอียดเพิ่มเติมเกี่ยวกับจำนวนบิตแต่ละประเภทที่ต้องมี: ประเภท intซึ่งกำหนดไว้ในมาตรฐาน

ฉันหวังว่านี่จะช่วยได้!



7

คุณสามารถใช้ได้:

cout << "size of datatype = " << sizeof(datatype) << endl;

datatype = int, long intฯลฯ คุณจะสามารถดูภาพขนาดสำหรับแล้วแต่จำนวนใดประเภทข้อมูลที่คุณพิมพ์


7

เมื่อพูดถึงการสร้างชนิดสำหรับสถาปัตยกรรมที่แตกต่างและคอมไพเลอร์ต่าง ๆ ให้รันโค้ดต่อไปนี้บนสถาปัตยกรรมของคุณด้วยคอมไพเลอร์ของคุณเพื่อดูว่ามันทำงานอะไร ด้านล่างแสดงUbuntu 13.04ของฉัน(Raring Ringtail) เอาต์พุต 64 บิต g ++ 4.7.3 นอกจากนี้โปรดทราบสิ่งที่ได้รับคำตอบด้านล่างซึ่งเป็นสาเหตุที่สั่งซื้อออกเช่น:

"มีจำนวนเต็มลงนามมาตรฐานห้าประเภท: ลงชื่อ char, short int, int, long int และ long long int ในรายการนี้แต่ละประเภทให้พื้นที่เก็บข้อมูลอย่างน้อยเท่ากับที่อยู่ก่อนหน้าในรายการ"

#include <iostream>

int main ( int argc, char * argv[] )
{
  std::cout<< "size of char: " << sizeof (char) << std::endl;
  std::cout<< "size of short: " << sizeof (short) << std::endl;
  std::cout<< "size of int: " << sizeof (int) << std::endl;
  std::cout<< "size of long: " << sizeof (long) << std::endl;
  std::cout<< "size of long long: " << sizeof (long long) << std::endl;

  std::cout<< "size of float: " << sizeof (float) << std::endl;
  std::cout<< "size of double: " << sizeof (double) << std::endl;

  std::cout<< "size of pointer: " << sizeof (int *) << std::endl;
}


size of char: 1
size of short: 2
size of int: 4
size of long: 8
size of long long: 8
size of float: 4
size of double: 8
size of pointer: 8

sizeof(char)ไม่ควรรวม
Ven

3

ขนาดดังกล่าวควรสะท้อนถึงสถาปัตยกรรมปัจจุบัน คุณอาจใช้จุดสูงสุดlimits.hหากคุณต้องการดูว่าคอมไพเลอร์ปัจจุบันของคุณจัดการกับสิ่งต่าง ๆ อย่างไร


ขอบคุณ แต่ฉันอยากรู้ขนาดของอาการปวดเมื่อยฉันไม่มีกล้ามเนื้อ (เช่น 64 บิต) บทช่วยสอนนี้จะพูดถึง achitectures
Jérôme

2

ดังที่คนอื่น ๆ ได้ตอบว่า "มาตรฐาน" ทุกคนปล่อยให้รายละเอียดส่วนใหญ่เป็น "การดำเนินการที่กำหนดไว้" และระบุเพียงว่าประเภท "ถ่าน" อยู่ที่ leat "char_bis" กว้างและ "ถ่าน <= สั้น <= int <= ยาว < = long long "(float และ double ค่อนข้างสอดคล้องกับมาตรฐาน IEEE floating point มากและโดยทั่วไป double long จะเป็น double - แต่อาจใหญ่กว่าในการใช้งานในปัจจุบันมากขึ้น)

สาเหตุส่วนหนึ่งที่ไม่มีค่าเฉพาะเจาะจงมากและแน่นอนเพราะภาษาเช่น C / C ++ ได้รับการออกแบบให้พกพาไปยังแพลตฟอร์มฮาร์ดแวร์จำนวนมาก - รวมถึงระบบคอมพิวเตอร์ที่ขนาดตัวอักษร "char" อาจเป็น 4 บิต หรือ 7 บิตหรือแม้กระทั่งค่าบางอย่างที่ไม่ใช่คอมพิวเตอร์ "8- / 16- / 32- / 64- บิต" ที่ผู้ใช้คอมพิวเตอร์ที่บ้านโดยเฉลี่ยจะสัมผัสกับ (ขนาดของ Word ที่นี่หมายถึงความกว้างของบิตที่ระบบทำงานตามปกติ - อีกครั้งมันไม่ได้เป็น 8-bits อย่างที่ผู้ใช้คอมพิวเตอร์ในบ้านคาดไว้)

หากคุณต้องการวัตถุจริงๆ (ในแง่ของชุดของบิตที่แสดงถึงค่าอินทิกรัล) ของจำนวนบิตที่เฉพาะเจาะจงคอมไพเลอร์ส่วนใหญ่มีวิธีการระบุว่า แต่โดยทั่วไปมันไม่ได้พกพาแม้ระหว่างคอมไพเลอร์ที่ทำโดย บริษัท ame แต่สำหรับแพลตฟอร์มที่แตกต่างกัน มาตรฐานและการปฏิบัติบางอย่าง (โดยเฉพาะอย่างยิ่งขีด จำกัด . h และที่คล้ายกัน) เป็นเรื่องธรรมดาพอที่คอมไพเลอร์ส่วนใหญ่จะได้รับการสนับสนุนในการกำหนดประเภทที่เหมาะสมที่สุดสำหรับช่วงของค่าเฉพาะ แต่ไม่ใช่จำนวนบิตที่ใช้ (นั่นคือถ้าคุณรู้ว่าคุณจำเป็นต้องเก็บค่าระหว่าง 0 และ 127 คุณสามารถตรวจสอบว่าคอมไพเลอร์ของคุณสนับสนุนประเภท "int8" 8 บิตซึ่งจะมีขนาดใหญ่พอที่จะเก็บไว้เต็มช่วงที่ต้องการ แต่ไม่ใช่สิ่งที่ต้องการ ประเภท "int7" ซึ่งจะเป็นการจับคู่ที่ตรงกันสำหรับ 7 บิต)

หมายเหตุ: แพ็คเกจ Un Un * x จำนวนมากใช้สคริปต์ "./configure" ซึ่งจะตรวจสอบความสามารถของคอมไพเลอร์ / ระบบและส่งออก Makefile และ config.h ที่เหมาะสม คุณอาจตรวจสอบสคริปต์เหล่านี้บางส่วนเพื่อดูวิธีการทำงานและวิธีตรวจสอบความสามารถของ comiler / ระบบและติดตามลูกค้าเป้าหมาย


1

หากคุณสนใจในโซลูชัน C ++ ที่แท้จริงฉันใช้เทมเพลตและรหัสมาตรฐาน C ++ เท่านั้นเพื่อกำหนดประเภทในเวลาคอมไพล์ตามขนาดบิตของพวกเขา ทำให้โซลูชันนี้สามารถพกพาข้ามคอมไพเลอร์ได้

แนวคิดที่อยู่เบื้องหลังนั้นง่ายมาก: สร้างรายการที่มีประเภท char, int, short, long, long (เวอร์ชันที่ลงชื่อและไม่ได้ลงนาม) และสแกนรายการและโดยใช้เทมเพลต numeric_limits เลือกประเภทที่มีขนาดที่กำหนด

การรวมส่วนหัวนี้คุณมี 8 ชนิด stdtype :: int8, stdtype :: int16, stdtype :: int32, stdtype :: int64, stdtype :: uint8, stdtype :: uint16, stdtype :: uint64

หากไม่สามารถแสดงบางประเภทมันจะถูกประเมินเป็น stdtype :: null_type ที่ประกาศในส่วนหัวด้วย

รหัสด้านล่างให้โดยไม่มีการรับประกันโปรดตรวจสอบสองครั้งมัน
ฉันใหม่ที่ METAPROGRAMMING TOO รู้สึกฟรีเพื่อแก้ไขและแก้ไขรหัสนี้
ทดสอบกับ DevC ++ (เวอร์ชั่น gcc ราว ๆ 3.5)

#include <limits>

namespace stdtype
{
    using namespace std;


    /*
     * THIS IS THE CLASS USED TO SEMANTICALLY SPECIFY A NULL TYPE.
     * YOU CAN USE WHATEVER YOU WANT AND EVEN DRIVE A COMPILE ERROR IF IT IS 
     * DECLARED/USED.
     *
     * PLEASE NOTE that C++ std define sizeof of an empty class to be 1.
     */
    class null_type{};

    /*
     *  Template for creating lists of types
     *
     *  T is type to hold
     *  S is the next type_list<T,S> type
     *
     *  Example:
     *   Creating a list with type int and char: 
     *      typedef type_list<int, type_list<char> > test;
     *      test::value         //int
     *      test::next::value   //char
     */
    template <typename T, typename S> struct type_list
    {
        typedef T value;
        typedef S next;         

    };




    /*
     * Declaration of template struct for selecting a type from the list
     */
    template <typename list, int b, int ctl> struct select_type;


    /*
     * Find a type with specified "b" bit in list "list"
     *
     * 
     */
    template <typename list, int b> struct find_type
    {   
        private:
            //Handy name for the type at the head of the list
            typedef typename list::value cur_type;

            //Number of bits of the type at the head
            //CHANGE THIS (compile time) exp TO USE ANOTHER TYPE LEN COMPUTING
            enum {cur_type_bits = numeric_limits<cur_type>::digits};

        public:
            //Select the type at the head if b == cur_type_bits else
            //select_type call find_type with list::next
            typedef  typename select_type<list, b, cur_type_bits>::type type;
    };

    /*
     * This is the specialization for empty list, return the null_type
     * OVVERRIDE this struct to ADD CUSTOM BEHAVIOR for the TYPE NOT FOUND case
     * (ie search for type with 17 bits on common archs)
     */
    template <int b> struct find_type<null_type, b>
    {   
        typedef null_type type;

    };


    /*
     * Primary template for selecting the type at the head of the list if
     * it matches the requested bits (b == ctl)
     *
     * If b == ctl the partial specified templated is evaluated so here we have
     * b != ctl. We call find_type on the next element of the list
     */
    template <typename list, int b, int ctl> struct select_type
    {   
            typedef  typename find_type<typename list::next, b>::type type; 
    };

    /*
     * This partial specified templated is used to select top type of a list
     * it is called by find_type with the list of value (consumed at each call)
     * the bits requested (b) and the current type (top type) length in bits
     *
     * We specialice the b == ctl case
     */
    template <typename list, int b> struct select_type<list, b, b>
    {
            typedef typename list::value type;
    };


    /*
     * These are the types list, to avoid possible ambiguity (some weird archs)
     * we kept signed and unsigned separated
     */

    #define UNSIGNED_TYPES type_list<unsigned char,         \
        type_list<unsigned short,                           \
        type_list<unsigned int,                             \
        type_list<unsigned long,                            \
        type_list<unsigned long long, null_type> > > > >

    #define SIGNED_TYPES type_list<signed char,         \
        type_list<signed short,                         \
        type_list<signed int,                           \
        type_list<signed long,                          \
        type_list<signed long long, null_type> > > > >



    /*
     * These are acutally typedef used in programs.
     * 
     * Nomenclature is [u]intN where u if present means unsigned, N is the 
     * number of bits in the integer
     *
     * find_type is used simply by giving first a type_list then the number of 
     * bits to search for.
     *
     * NB. Each type in the type list must had specified the template 
     * numeric_limits as it is used to compute the type len in (binary) digit.
     */
    typedef find_type<UNSIGNED_TYPES, 8>::type  uint8;
    typedef find_type<UNSIGNED_TYPES, 16>::type uint16;
    typedef find_type<UNSIGNED_TYPES, 32>::type uint32;
    typedef find_type<UNSIGNED_TYPES, 64>::type uint64;

    typedef find_type<SIGNED_TYPES, 7>::type    int8;
    typedef find_type<SIGNED_TYPES, 15>::type   int16;
    typedef find_type<SIGNED_TYPES, 31>::type   int32;
    typedef find_type<SIGNED_TYPES, 63>::type   int64;

}

0
unsigned char bits = sizeof(X) << 3;

ที่Xเป็นchar, int, longฯลฯ .. จะให้ขนาดของXในบิต


1
ถ่านไม่ใช่ 8 บิตเสมอดังนั้นนิพจน์ของคุณจะไม่ทำงาน สถาปัตยกรรมกับถ่านไม่ใช่ 8 บิต sizeof(type)*CHAR_BITถือครองเท่านั้น
phuclv

แม้ว่าCHAR_BITได้รับการรับประกันว่าจะ 8 บิต<< 3เป็นเพียงวิธีที่ปกปิดการเขียนหรือ* 8 * CHAR_BIT
Keith Thompson

0

จาก Alex B มาตรฐาน C ++ ไม่ได้ระบุขนาดของอินทิกรัลชนิดเป็นไบต์ แต่ระบุช่วงต่ำสุดที่พวกเขาต้องสามารถเก็บได้ คุณสามารถอนุมานขนาดขั้นต่ำเป็นบิตจากช่วงที่ต้องการ คุณสามารถอนุมานขนาดขั้นต่ำเป็นไบต์จากนั้นและค่าของแมโค CHAR_BIT ที่กำหนดจำนวนบิตในไบต์ (ในทั้งหมดยกเว้นแพลตฟอร์มที่คลุมเครือมากที่สุดคือ 8 และจะต้องไม่น้อยกว่า 8)

ข้อ จำกัด เพิ่มเติมสำหรับ char คือขนาดของมันคือ 1 ไบต์เสมอหรือบิต CHAR_BIT (ดังนั้นชื่อ)

ช่วงต่ำสุดที่มาตรฐานกำหนด (หน้า 22) คือ:

และช่วงชนิดข้อมูลบน MSDN:

ถ่านที่ลงนามแล้ว: -127 ถึง 127 (หมายเหตุไม่ใช่ -128 ถึง 127 ซึ่งรองรับแพลตฟอร์ม 1's) ประกอบไปด้วยถ่านที่ไม่ได้ลงชื่อ: 0 ถึง 255 "ธรรมดา" ถ่าน: -127 ถึง 127 หรือ 0 ถึง 255 (ขึ้นอยู่กับการลงนามเริ่มต้นของถ่าน) สั้น: -32767 ถึง 32767 ไม่ได้ลงนามสั้น: 0 ถึง 65535 ลงนาม int: -32767 ถึง 32767 ไม่ลงนาม int: 0 ถึง 65535 ลงนามยาว: -2147483647 ถึง 2147483647 ยาวไม่ได้ลงนาม: 0 ถึง 4294967295 ลงนามยาวนาน: -922337203647758080780 0 ถึง 18446744073709551615 การใช้ C ++ (หรือ C) สามารถกำหนดขนาดของประเภทเป็นไบต์ขนาดของ (ชนิด) เป็นค่าใดก็ได้ตราบใดที่

ขนาดนิพจน์ (ชนิด) * CHAR_BIT ประเมินเป็นจำนวนบิตเพียงพอที่จะมีช่วงที่ต้องการและการเรียงลำดับประเภทยังคงใช้ได้ (เช่นขนาดของ (int) <= sizeof (ยาว)) ช่วงเฉพาะของการนำไปใช้งานจริงสามารถพบได้ในส่วนหัวใน C หรือใน C ++ (หรือดีกว่า templated std :: numeric_limits ในส่วนหัว)

ตัวอย่างเช่นนี่คือวิธีที่คุณจะค้นหาช่วงสูงสุดสำหรับ int:

ค:

#include <limits.h>
const int min_int = INT_MIN;
const int max_int = INT_MAX;

C ++:

#include <limits>
const int min_int = std::numeric_limits<int>::min();
const int max_int = std::numeric_limits<int>::max();

สิ่งนี้ถูกต้องอย่างไรก็ตามคุณพูดถูก: char: 1 ไบต์สั้น: 2 ไบต์ int: 4 ไบต์ยาว: 4 ไบต์ลอย: 4 ไบต์คู่: 8 ไบต์

เนื่องจากสถาปัตยกรรม 32 บิตยังคงเป็นค่าเริ่มต้นและใช้งานมากที่สุดและยังคงรักษาขนาดมาตรฐานเหล่านี้ไว้ตั้งแต่ 32 บิตวันก่อนที่หน่วยความจำจะพร้อมใช้งานน้อยลง แม้แต่ระบบ 64 บิตมักจะใช้สิ่งเหล่านี้และมีขอบเขต / การปรับเปลี่ยน โปรดอ้างอิงสิ่งนี้สำหรับข้อมูลเพิ่มเติม:

http://en.cppreference.com/w/cpp/language/types


0

ฉันสังเกตเห็นว่าคำตอบอื่น ๆ ทั้งหมดที่นี่เน้นเฉพาะประเภทที่ครบถ้วนในขณะที่ผู้ถามยังถามเกี่ยวกับคะแนนแบบลอยตัว

ฉันไม่คิดว่ามาตรฐาน C ++ ต้องการมัน แต่คอมไพเลอร์สำหรับแพลตฟอร์มที่พบบ่อยที่สุดในปัจจุบันมักเป็นไปตามมาตรฐาน IEEE754 สำหรับตัวเลขทศนิยม มาตรฐานนี้ระบุจุดลอยตัวไบนารี่สี่ประเภท (รวมถึงรูปแบบ BCD บางรูปแบบซึ่งฉันไม่เคยเห็นสนับสนุนในคอมไพเลอร์ C ++):

  • Half precision (binary16) - ซิกนิค 11 บิตช่วงเลขชี้กำลัง -14 ถึง 15
  • ความแม่นยำเดี่ยว (binary32) - ความสำคัญ 24 บิตช่วงเลขชี้กำลัง -126 ถึง 127
  • ความแม่นยำสองเท่า (ไบนารี 64) - ซิกนิฟิแคนด์ 53 บิตช่วงเลขชี้กำลัง -1022 ถึง 1,023
  • ความแม่นยำสี่เท่า (ไบนารี128) - ซิกนิฟิแคนด์ 113 บิต, เลขชี้กำลัง -16382 ถึง 16383

แผนที่นี้ใช้กับประเภท C ++ อย่างไร โดยทั่วไปแล้วfloatใช้ความแม่นยำเดียว; sizeof(float) = 4จึง จากนั้นdoubleใช้ความแม่นยำสองเท่า (ฉันเชื่อว่าเป็นแหล่งที่มาของชื่อdouble) และlong doubleอาจเป็นความแม่นยำสองเท่าหรือสี่เท่า (เป็นสี่เท่าในระบบของฉัน แต่ในระบบ 32 บิตมันอาจเป็นสองเท่า) ฉันไม่รู้คอมไพเลอร์ใด ๆ ที่เสนอจุดลอยตัวที่มีความแม่นยำเพียงครึ่งเดียว

โดยสรุปนี่เป็นเรื่องปกติ:

  • sizeof(float) = 4
  • sizeof(double) = 8
  • sizeof(long double) = 8 หรือ 16

ตลกที่ฉันมาถึงคำถามนี้เป็นส่วนหนึ่งของความสงสัยว่าทำไมเจฟใช้จำนวนไบต์มากกว่าที่เขาต้องการ
Aniruddha Varma

-1

ดังที่คุณกล่าวถึง - ส่วนใหญ่ขึ้นอยู่กับคอมไพเลอร์และแพลตฟอร์ม สำหรับสิ่งนี้ให้ตรวจสอบมาตรฐาน ANSI, http://home.att.net/~jackklein/c/inttypes.html

นี่คือหนึ่งสำหรับคอมไพเลอร์ของ Microsoft: ชนิดข้อมูล Ranges


-2

คุณสามารถใช้ตัวแปรที่มีให้โดยไลบรารีเช่นOpenGL , Qtเป็นต้น

ตัวอย่างเช่น Qt มี qint8 (รับประกันว่าจะเป็น 8 บิตในทุกแพลตฟอร์มที่สนับสนุนโดย Qt), qint16, qint32, qint64, quint8, quint16, quint32, quint64 ฯลฯ


1
ไม่ตอบคำถาม
EvilTeach

-8

บนเครื่อง 64 บิต:

int: 4
long: 8
long long: 8
void*: 8
size_t: 8

2
ในเครื่อง 64 บิตบางเครื่องintมีขนาด 8 ไบต์ แต่เครื่องอื่นไม่รับประกัน ไม่มีอะไรที่บอกว่าcharควรจะมีเพียง 8 บิต ได้รับอนุญาตให้มีsizeof(void*)==4แม้ว่าจะเป็น 64 บิต
58

-10

มีจำนวนเต็มสี่ชนิดตามขนาด:

  • จำนวนเต็มสั้น: 2 ไบต์
  • จำนวนเต็มแบบยาว: 4 ไบต์
  • จำนวนเต็มยาวยาว: 8 ไบต์
  • จำนวนเต็ม: ขึ้นอยู่กับคอมไพเลอร์ (16 บิต, 32 บิตหรือ 64 บิต)

11
เท็จพวกเขาทั้งหมดขึ้นอยู่กับสถาปัตยกรรมที่มีช่วงต่ำสุดที่อธิบายไว้ในหนึ่งในคำตอบอื่น ๆ ไม่มีอะไรหยุดการดำเนินการที่จะมีshort, intและlongทุกจำนวนเต็ม 32 บิต
Matteo Italia

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