มีเครื่องจักรที่ sizeof (ถ่าน)! = 1 หรืออย่างน้อย CHAR_BIT> 8 หรือไม่


93

มีเครื่องจักร (หรือคอมไพเลอร์) อยู่ที่ไหนsizeof(char) != 1?

ไม่มาตรฐาน C99กล่าวว่าsizeof(char)ในการดำเนินการปฏิบัติตามมาตรฐานต้องเป็น 1? ถ้าเป็นเช่นนั้นโปรดให้หมายเลขมาตราและการอ้างอิง

อัปเดต: หากฉันมีเครื่อง (CPU) ซึ่งไม่สามารถระบุไบต์ได้ (อ่านน้อยที่สุดคือ 4 ไบต์จัดแนว) แต่มีไบต์เพียง 4 วินาที ( uint32_t) คอมไพเลอร์สำหรับเครื่องนี้สามารถกำหนดsizeof(char)เป็น 4 ได้หรือไม่ sizeof(char)จะเป็น 1 แต่ถ่านจะมี 32 บิต ( CHAR_BITมาโคร)

Update2: แต่ขนาดของผลลัพธ์ไม่ใช่ไบต์! มีขนาดเท่ากับ CHAR และถ่านสามารถเป็น 2 ไบต์หรือ (อาจเป็น) 7 บิต?

Update3: ตกลง เครื่องทั้งหมดมีsizeof(char) == 1. แต่มีเครื่องCHAR_BIT > 8อะไรบ้าง?


4
ฉันกังวลในการปฏิบัติตามมาตรฐาน C99 ฉันทำงานอย่างใกล้ชิดกับคอมไพเลอร์ C99
osgx

2
เนื่องจาก Unicode มีความสำคัญมากขึ้นอาจมีคอมไพเลอร์ที่ไม่ได้มาตรฐานซึ่งใช้อักขระ Unicode เป็นchar(แทนwchar) แม้ว่ามาตรฐานจะระบุว่าsizeof(char)ต้องเป็น 1 แต่ฉันก็ไม่ใช้สมมติฐานนั้น
Chip Uni

14
ไม่มีคอมไพเลอร์ C ที่ sizeof (ถ่าน) ไม่ใช่ 1 ยูนิโคดหรือไม่
เลขที่

6
@Chip: sizeof(char)เป็น 1 เสมอแม้ว่า char จะเป็น 32 บิต (เช่นเดียวกับที่เกิดขึ้นในบางระบบ) C มีหูดที่สนุกสนานมากมาย
Nick Bastin

2
มาตรฐาน C ทุกเวอร์ชันกำหนดให้ CHAR_BIT มีค่าอย่างน้อย 8 คุณไม่สามารถมี CHAR_BIT == 7 และเป็นไปตามมาตรฐาน อย่างไรก็ตามมันเป็นไปได้อย่างสมบูรณ์แบบสำหรับเครื่องจักรที่จะมี CHAR_BIT> 8 เครื่อง Cray รุ่นเก่าฉันเชื่อ ( sizeof(char) == sizeof(short) && sizeof(char) == sizeof(int)ในเครื่องเหล่านั้นฉันจำไม่ได้sizeof(int) == sizeof(long)ว่า CHAR_BIT เป็น 32 หรือ 64 หรือไม่ฉันคาดหวังไว้ที่ 32 และฉันก็คิดsizeof(long) == 1เช่นกัน (คุณสามารถค้นหาข้อมูลอ้างอิงถึงคู่มือ Cray Cแต่ไม่สามารถเข้าถึงได้ทางออนไลน์)
Jonathan Leffler

คำตอบ:


91

เป็นหนึ่งใน C99 เสมอส่วน 6.5.3.4:

เมื่อนำไปใช้กับตัวถูกดำเนินการที่มีประเภท char, char ที่ไม่ได้ลงนามหรือ char ที่ลงนาม (หรือเวอร์ชันที่มีคุณสมบัติเหมาะสม) ผลลัพธ์คือ 1

แก้ไข: ไม่ใช่ส่วนหนึ่งของคำถามของคุณ แต่เพื่อความสนใจจาก Harbison and Steele, 3rd ed (ก่อน c99) น. 148:

หน่วยเก็บข้อมูลถูกนำไปเป็นจำนวนหน่วยเก็บข้อมูลที่ครอบครองโดยหนึ่งอักขระ ขนาดของวัตถุประเภทcharจึงเท่ากับ 1

แก้ไข: ในคำตอบสำหรับคำถามที่อัปเดตของคุณคำถามและคำตอบต่อไปนี้จาก Harbison และ Steele มีความเกี่ยวข้อง (อ้างแล้ว, เช่น 4 ของ Ch.6):

อนุญาตให้มีการใช้งาน C ประเภทcharใดบ้างที่สามารถแสดงค่าตั้งแต่ -2,147,483,648 ถึง 2,147,483,647 ถ้าเป็นเช่นนั้นสิ่งที่จะอยู่sizeof(char) ภายใต้การนำไปใช้นั้น? ช่วงที่เล็กที่สุดและใหญ่ที่สุดintคืออะไร?

คำตอบ (อ้างแล้วหน้า 382):

มันจะได้รับอนุญาต (ถ้าสิ้นเปลือง) สำหรับการดำเนินงานที่จะใช้ 32 charบิตเพื่อเป็นตัวแทนของประเภท โดยไม่คำนึงถึงการนำไปใช้ค่าของ sizeof(char)จะเป็น 1 เสมอ

แม้ว่าสิ่งนี้จะไม่ได้กล่าวถึงกรณีที่เฉพาะเจาะจง แต่ไบต์คือ 8 บิตและcharเป็น 4 ไบต์เหล่านั้น (เป็นไปไม่ได้จริง ๆ กับนิยาม c99 ดูด้านล่าง) ความจริงที่sizeof(char) = 1ชัดเจนจากมาตรฐาน c99 และ Harbison และ Steele เสมอ

แก้ไข: ในความเป็นจริง (นี้ในการตอบสนองต่อ UPD 2 คำถามของคุณ) เท่าที่ c99 เป็นห่วงsizeof(char) เป็นไบต์จากส่วน 6.5.3.4 อีกครั้ง:

ตัวดำเนินการ sizeof ให้ขนาด (เป็นไบต์) ของตัวถูกดำเนินการ

ดังนั้นเมื่อรวมกับใบเสนอราคาด้านบนไบต์ 8 บิตและchar4 ไบต์เหล่านั้นจึงเป็นไปไม่ได้: สำหรับ c99 a ไบต์จะเหมือนกับ a char.

ในคำตอบของคุณเกี่ยวกับความเป็นไปได้ของ 7 bit char: เป็นไปไม่ได้ใน c99 ตามมาตรา 5.2.4.2.1 ของมาตรฐานขั้นต่ำคือ 8:

ค่าที่กำหนดการนำไปใช้งานจะต้องมีขนาดเท่ากันหรือมากกว่า [เน้นของฉัน] ตามขนาดที่แสดงโดยมีเครื่องหมายเดียวกัน

- จำนวนบิตสำหรับวัตถุที่เล็กที่สุดที่ไม่ใช่บิตฟิลด์ (ไบต์)

 **CHAR_BIT 8**

- ค่าต่ำสุดสำหรับวัตถุประเภทถ่านที่เซ็นชื่อ

**SCHAR_MIN -127//−(27−1)** 

- ค่าสูงสุดสำหรับวัตถุประเภทถ่านที่เซ็นชื่อ

**SCHAR_MAX +127//27−1** 

- ค่าสูงสุดสำหรับวัตถุประเภทถ่านที่ไม่ได้ลงชื่อ

**UCHAR_MAX 255//28−1** 

- ค่าต่ำสุดสำหรับวัตถุประเภทถ่าน

**CHAR_MIN**    see below 

- ค่าสูงสุดสำหรับวัตถุประเภทถ่าน

**CHAR_MAX**    see below

[... ]

หากค่าของอ็อบเจ็กต์ประเภท char ถูกถือว่าเป็นจำนวนเต็มที่มีลายเซ็นเมื่อใช้ในนิพจน์ค่าของ CHAR_MIN จะเหมือนกับของ SCHAR_MIN และค่าของ CHAR_MAX จะเท่ากับของ SCHAR_MAX มิฉะนั้นค่าของ CHAR_MIN จะเป็น 0 และค่าของ CHAR_MAX จะเหมือนกับของ UCHAR_MAX ค่า UCHAR_MAX จะเท่ากับ 2 ^ CHAR_BIT - 1


9
หมายเหตุเพิ่มเติม มีมาโคร CHAR_BITS ที่จะบอกคุณว่าอักขระของคุณมีกี่บิต
เลขที่

1
ข้อมูลทั้งหมดของหนังสือเล่มนี้คือHarbison และ Steele's C: A Reference Manual, Third Edition, Prentice Hall, 1991
osgx

2
หากคุณรู้ว่าคุณกำลังทำงานกับประเภทถ่านและคุณรู้ว่าภาษากำหนดให้มีขนาด 1 เหตุใดจึงควรใส่ขนาดที่ซ้ำซ้อนของ (ถ่าน) อยู่เสมอ

1
(a) และ (c) มีการแบ่งส่วนที่รุนแรงมากขึ้นซึ่งไม่สามารถหวังว่าจะแก้ไขได้หรือแม้แต่เข้าใกล้การแก้ไข YAGNI ด้วย ใครบางคนใน (b) ต้องได้รับการบอกเล่าเพียงครั้งเดียว - ฉันไม่จำเป็นต้องสอนพวกเขาในทุกบรรทัดของรหัสของฉัน อย่างไรก็ตามมีข้อเสียในการใช้sizeof(char): เป็นอีกหนึ่งรายการที่จะอภิปราย / ตรวจสอบ / ฯลฯ ในรูปแบบ / มาตรฐาน / แนวทางการเข้ารหัสของคุณทำให้ฉันเสียเวลาสงสัยว่าคุณรู้ C จริงหรือไม่และมีอะไรที่อาจไม่ถูกต้องใช้ "แบนด์วิดท์" แบบแสดงภาพ / จิต / ข้อความ

1
@Ramashalanka: ใช่รหัสที่คอมไพล์เทียบเท่า ปัญหาทั้งหมดเกี่ยวกับความสามารถในการอ่านและวิธีอื่น ๆ ที่ผู้คนใช้ซอร์สโค้ดที่ฉันกำลังพูดถึง (และ FWIW ฉันคิดว่าคุณมีคำตอบ +1 ที่ดีที่นี่ฉันพบว่า "ใช้ sizeof (ถ่าน)" เสมอเพื่อให้เข้าใจผิดและเป็นปัญหาปุ่มลัดสำหรับฉันแม้ว่าจะเป็นปัญหาเล็กน้อยก็ตาม)

21

ไม่มีเครื่องจักรที่sizeof(char)เป็น 4 มันจะเป็น 1 ไบต์เสมอ ไบต์นั้นอาจมี 32 บิต แต่เท่าที่เกี่ยวข้องกับคอมไพเลอร์ C มันคือหนึ่งไบต์ สำหรับรายละเอียดเพิ่มเติมฉันจริงจะชี้ให้คุณที่C ++ คำถามที่พบบ่อย 26.6 ลิงก์นั้นครอบคลุมมันค่อนข้างดีและฉันค่อนข้างมั่นใจว่า C ++ ได้รับกฎเหล่านั้นทั้งหมดจาก C คุณยังสามารถดูcomp.lang.c FAQ 8.10สำหรับอักขระที่มีขนาดใหญ่กว่า 8 บิต

Upd2: แต่ขนาดของผลลัพธ์ไม่ใช่ไบต์! มีขนาดเท่ากับ CHAR และถ่านสามารถเป็น 2 ไบต์หรือ (อาจเป็น) 7 บิต?

ใช่มันเป็นไบต์ ให้ฉันพูดอีกครั้ง sizeof(char)คือ 1 ไบต์ตามคอมไพเลอร์ C สิ่งที่คนทั่วไปเรียกว่าไบต์ (8 บิต) นั้นไม่จำเป็นต้องเหมือนกับสิ่งที่คอมไพเลอร์ C เรียกว่าไบต์ จำนวนบิตใน C byte จะแตกต่างกันไปขึ้นอยู่กับสถาปัตยกรรมเครื่องของคุณ นอกจากนี้ยังรับประกันว่าต้องมีอย่างน้อย 8


3
กรุณา!!! C ++ เป็นภาษาที่แตกต่างจาก C (C99) คำถามนี้เกี่ยวกับ C ธรรมดาเท่านั้น
osgx

<strike> ฉันจะทำอย่างไรเมื่อเครื่อง / CPU ไม่สามารถเข้าถึง 8-bit bytes? ไม่อนุญาตให้เข้าถึงที่ไม่ตรงแนว </strike> (แม้ใน x86 malloc จะส่งคืนข้อมูลที่จัดแนวและจัดสรรหน่วยความจำเป็นทวีคูณ 4 ไบต์) <strike> ดังนั้น CHAT_BIT จะมากกว่า 8 ใช่แพลตฟอร์มดังกล่าวอาจค่อนข้างพิเศษ </ strike >
osgx

11
@osgx ฉันมักจะกรีดร้องมากพอ ๆ กับที่คุณทำเมื่อมีคนพยายามผสม C และ C ++ แต่ฉันคิดว่าในกรณีนี้รายการคำถามที่พบบ่อย C ++ หนึ่งรายการใช้ได้ดีกับ C.
Michael Kristofik

3
ชื่อที่ถูกต้องสำหรับ "8 บิต" คือ octet มาตรฐาน C ใช้คำว่า "ไบต์" สำหรับวัตถุที่มีขนาดเท่ากับถ่าน คนอื่นอาจใช้คำว่า "byte" ในรูปแบบที่แตกต่างกันโดยมากมักหมายถึง "octet" แต่ในภาษา C (และ C ++ หรือ Objective-C) หมายถึง "วัตถุขนาดเท่าถ่าน" ถ่านอาจมากกว่า 8 บิตหรือมากกว่าหนึ่งอ็อกเต็ต แต่จะเป็นหนึ่งไบต์เสมอ
gnasher729

9

PDP-10 และ PDP-11คือ.

อัปเดต: ไม่มีคอมไพเลอร์ C99 สำหรับ PDP-10

บางรุ่นของอุปกรณ์อะนาล็อก 32 บิต SHARC DSP มี CHAR_BIT = 32, และ Texas Instruments DSP จาก TMS32F28xx มี CHAR_BIT = 16 มีรายงานว่า

อัปเดต: มีGCC 3.2 สำหรับ PDP-10พร้อม CHAR_BIT = 9 (ตรวจสอบรวม ​​/ จำกัด h ในที่เก็บถาวรนั้น)


1
อย่าสับสนระหว่างการใช้ภาษา C ที่คล้ายกัน แต่ไม่ใช่ภาษาซีคุณถึงกับพูดว่า "ฉันกังวลในการปฏิบัติตามมาตรฐาน C99 ฉันทำงานอย่างใกล้ชิดกับคอมไพเลอร์ C99"

2
@ Roger: ไม่ยุติธรรมที่จะเรียก GCC3 ว่าไม่เป็นไปตาม C99 เว้นแต่คุณจะต้องรับมือกับกรณีที่มีขอบมากซึ่งถือว่าเป็นข้อบกพร่องใน GCC
Joshua

1
@ โจชัวฉันคิดว่าโรเจอร์พูดเกี่ยวกับคอมไพเลอร์ประวัติศาสตร์ K&R และ pcc นอกจากนี้ยังไม่ยุติธรรมที่จะอ้างว่าเป็นไปตามมาตรฐาน C99 ก่อนที่ชุดทดสอบการปฏิบัติตามข้อกำหนด C99 จะทำงานบน PDP-10 เมื่อคอมไพล์ด้วยพอร์ตนี้ (อาจมีข้อบกพร่องจากการพอร์ตและจากเครื่องเอง) แต่คาดว่าจะใกล้เคียงกับมาตรฐาน C99 เช่นเดียวกับ GCC3.2 บน x86
osgx

1
@ โจชัว: CHAR_BIT ได้รับอนุญาตใน C99 ให้มากกว่า 8 แต่ sizeof (ถ่าน) ต้องเป็น 1 (และคำตอบนี้แตกต่างกันมากเมื่อฉันแสดงความคิดเห็นนั้น) ฉันไม่ได้เรียกว่าไม่สอดคล้องกับ GCC3 และ C89 มีข้อกำหนดเดียวกันที่นี่ BTW ฉันอ้างข้อความนั้นเพื่อบอกว่า osgx เป็นคนที่กังวลเกี่ยวกับการปฏิบัติตามข้อกำหนดของ C99 และใช้คอมไพเลอร์ C99 ดังนั้นทำไมเขาถึงกังวลเกี่ยวกับคอมไพเลอร์ที่ไม่ใช่ C99

2
ผู้เขียน PDP-10 GCC ที่นี่ CHAR_BIT คือ 9 แต่ sizeof (ถ่าน) ยังคงเป็น 1
Lars Brinkhoff
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.