ตัวแปรเลขจำนวนเต็มใน 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)(เช่นความเข้าใจผิดที่พบบ่อยของจำนวนเต็มสองไบต์และสี่ไบต์ละเลยรายละเอียดเหล่านี้)