ตัวแปรเลขจำนวนเต็มใน C ใช้ 2 ไบต์หรือ 4 ไบต์หรือไม่
ขึ้นอยู่กับแพลตฟอร์มที่คุณใช้รวมถึงวิธีกำหนดค่าคอมไพเลอร์ของคุณ คำตอบเดียวที่เชื่อถือได้คือการใช้sizeof
โอเปอเรเตอร์เพื่อดูว่าจำนวนเต็มใหญ่แค่ไหนในสถานการณ์เฉพาะของคุณ
อะไรคือปัจจัยที่ขึ้นอยู่กับอะไร
ช่วงอาจจะถือว่าดีที่สุดมากกว่าขนาด ทั้งสองอย่างจะแตกต่างกันในทางปฏิบัติแม้ว่าจะเป็นเรื่องโง่มากที่จะเลือกประเภทของตัวแปรตามช่วงมากกว่าขนาดที่เราจะได้เห็น สิ่งสำคัญคือต้องทราบว่ามาตรฐานสนับสนุนให้เราพิจารณาเลือกประเภทจำนวนเต็มของเราตามช่วงแทนที่จะเป็นขนาดแต่ตอนนี้เราจะเพิกเฉยต่อการปฏิบัติตามมาตรฐานและให้ความอยากรู้สำรวจsizeof
ไบต์และCHAR_BIT
ตัวแทนจำนวนมาก ... ลองขุดลงมา หลุมกระต่ายและดูด้วยตัวเราเอง ...
sizeof
, ไบต์และ CHAR_BIT
คำสั่งต่อไปนี้นำมาจากมาตรฐาน C (เชื่อมโยงกับด้านบน) อธิบายสิ่งนี้ในคำที่ฉันไม่คิดว่าสามารถปรับปรุงได้
ตัวsizeof
ดำเนินการให้ผลขนาด (เป็นไบต์) ของตัวถูกดำเนินการซึ่งอาจเป็นนิพจน์หรือชื่อวงเล็บชนิด ขนาดถูกกำหนดจากชนิดของตัวถูกดำเนินการ
สมมติว่ามีความเข้าใจที่ชัดเจนจะนำเราไปสู่การอภิปรายเกี่ยวกับไบต์ ก็สันนิษฐานกันทั่วไปว่าไบต์เป็นแปดบิตในเมื่อความจริงจะบอกคุณว่ากี่บิตอยู่ในไบต์CHAR_BIT
นั่นเป็นเพียงหนึ่งในความแตกต่างที่ไม่ได้พิจารณาเมื่อพูดถึงจำนวนเต็มสอง (หรือสี่) ไบต์ทั่วไปทั่วไป
เรามาสรุปกัน:
sizeof
=> ขนาดเป็นไบต์และ
CHAR_BIT
=> จำนวนบิตเป็นไบต์
ดังนั้นขึ้นอยู่กับระบบของคุณsizeof (unsigned int)
อาจเป็นค่าใด ๆ ที่มากกว่าศูนย์ (ไม่ใช่แค่ 2 หรือ 4) ราวกับว่าCHAR_BIT
เป็น 16 แล้วไบต์เดียว (สิบหกบิต)มีบิตเพียงพอในนั้นเพื่อเป็นตัวแทนของจำนวนเต็มสิบหกบิตที่อธิบายโดย มาตรฐาน (ยกมาด้านล่าง) นั่นไม่ใช่ข้อมูลที่มีประโยชน์เสมอไปใช่ไหม มาเจาะลึกลงไป ...
การเป็นตัวแทนจำนวนเต็ม
ซีระบุมาตรฐานขั้นต่ำที่มีความแม่นยำ / ช่วงสำหรับทุกประเภทจำนวนเต็มมาตรฐาน (และCHAR_BIT
มากเกินไป FWIW) ที่นี่ จากนี้เราสามารถได้รับมาอย่างน้อยกี่บิตจะต้องเก็บค่าแต่เราอาจได้เป็นอย่างดีเพียงแค่เลือกตัวแปรของเราขึ้นอยู่กับช่วง อย่างไรก็ตามรายละเอียดส่วนใหญ่ที่จำเป็นสำหรับคำตอบนี้อยู่ที่นี่ ตัวอย่างเช่นต่อไปนี้ที่มาตรฐานunsigned int
ต้องการ (อย่างน้อย) หน่วยความจำสิบหกบิต:
UINT_MAX 65535 // 2¹⁶ - 1
ดังนั้นเราจะเห็นได้ว่าunsigned int
ต้องการ ( อย่างน้อย ) 16 บิตซึ่งเป็นที่ที่คุณได้รับสองไบต์ (สมมติว่าCHAR_BIT
เป็น 8) ... และต่อมาเมื่อขีด จำกัด นั้นเพิ่มขึ้น2³² - 1
ผู้คนจะระบุ 4 ไบต์แทน สิ่งนี้อธิบายถึงปรากฏการณ์ที่คุณสังเกตได้:
หนังสือเรียนส่วนใหญ่บอกว่าตัวแปรจำนวนเต็มมี 2 ไบต์ แต่เมื่อฉันรันโปรแกรมที่พิมพ์ที่อยู่ต่อเนื่องของอาร์เรย์จำนวนเต็มมันจะแสดงความแตกต่างของ 4
คุณกำลังใช้ตำราโบราณและผู้แปลซึ่งสอนคุณแบบพกพา C; ผู้แต่งที่เขียนตำราเรียนของคุณอาจไม่รู้CHAR_BIT
ตัว คุณควรอัพเกรดตำราเรียน (และคอมไพเลอร์) และพยายามจำไว้ว่าไอทีเป็นสาขาที่มีการพัฒนาตลอดเวลาที่คุณต้องอยู่ข้างหน้าเพื่อแข่งขัน ... เพียงพอสำหรับเรื่องนี้ เรามาดูกันว่าความลับที่ไม่ใช่แบบพกพาอื่น ๆ คืออะไรจำนวนเต็มไบต์ที่เก็บไว้ ...
บิตของค่าเป็นสิ่งที่ความเข้าใจผิดร่วมกันดูเหมือนจะนับ ตัวอย่างด้านบนใช้unsigned
ประเภทจำนวนเต็มซึ่งโดยทั่วไปจะมีเฉพาะค่าบิตดังนั้นจึงง่ายที่จะพลาดรายละเอียดมาร
Sign bits ... ในตัวอย่างข้างต้นฉันอ้างUINT_MAX
ว่ามันเป็นขีด จำกัด บนunsigned int
เพราะเป็นตัวอย่างเล็กน้อยที่จะดึงค่า16
จากความคิดเห็น สำหรับประเภทที่เซ็นชื่อเพื่อที่จะแยกแยะความแตกต่างระหว่างค่าบวกและลบ (นั่นคือเครื่องหมาย) เราต้องรวมบิตบิตด้วย
INT_MIN -32768 // -(2¹⁵)
INT_MAX +32767 // 2¹⁵ - 1
Padding bits ... แม้ว่าจะไม่ใช่เรื่องธรรมดาที่จะพบคอมพิวเตอร์ที่มี padding bits เป็นจำนวนเต็มก็ตามมาตรฐาน C อนุญาตให้เกิดขึ้นได้ เครื่องบางเครื่อง (เช่นนี้ ) ใช้ประเภทจำนวนเต็มขนาดใหญ่โดยรวมสองจำนวนเล็ก (ลงนาม) ค่าจำนวนรวมเข้าด้วยกัน ... และเมื่อคุณรวมจำนวนเต็มลงนามคุณจะได้รับบิตสัญญาณเสีย ที่สูญเสียบิตถือว่าเป็นช่องว่างใน C. ตัวอย่างอื่น ๆ ของบิต padding อาจรวมถึงบิตความเท่าเทียมกันและดักบิต
อย่างที่คุณเห็นมาตรฐานดูเหมือนว่าจะสนับสนุนการพิจารณาช่วงเช่นINT_MIN
.. INT_MAX
และค่าต่ำสุด / สูงสุดอื่น ๆ จากมาตรฐานเมื่อเลือกประเภทจำนวนเต็มและกีดกันที่ขึ้นอยู่กับขนาดเนื่องจากมีปัจจัยที่ลึกซึ้งอื่น ๆ ที่น่าจะลืมเช่นCHAR_BIT
บิตรอง อาจส่งผลกระทบต่อค่าของsizeof (int)
(เช่นความเข้าใจผิดที่พบบ่อยของจำนวนเต็มสองไบต์และสี่ไบต์ละเลยรายละเอียดเหล่านี้)