CHAR_BIT คืออะไร


93

การอ้างรหัสสำหรับการคำนวณค่าสัมบูรณ์จำนวนเต็ม (abs) โดยไม่แยกจากhttp://graphics.stanford.edu/~seander/bithacks.html :

int v;           // we want to find the absolute value of v
unsigned int r;  // the result goes here 
int const mask = v >> sizeof(int) * CHAR_BIT - 1;

r = (v + mask) ^ mask;

รูปแบบที่จดสิทธิบัตร:

r = (v ^ mask) - mask;

คืออะไรCHAR_BITและใช้อย่างไร?

คำตอบ:


0

คุณควรทราบว่ารหัสนี้ขึ้นอยู่กับลักษณะการใช้งานที่กำหนดไว้ของบิตชิฟต์ที่เหมาะสมในประเภทที่เซ็น gcc สัญญาว่าจะให้พฤติกรรมที่ดีเสมอ (sign-bit-extension) แต่ ISO C อนุญาตให้ใช้งานเพื่อเติมบิตด้านบนเป็นศูนย์

วิธีหนึ่งในการแก้ปัญหานี้:

#ifdef HAVE_SIGN_EXTENDING_BITSHIFT
int const mask = v >> sizeof(int) * CHAR_BIT - 1;
#else
int const mask = -((unsigned)v >> sizeof(int) * CHAR_BIT - 1);
#endif

ของคุณMakefileหรือconfig.hอื่น ๆ สามารถกำหนดHAVE_SIGN_EXTENDING_BITSHIFTในเวลาสร้างขึ้นอยู่กับแพลตฟอร์มของคุณ


122
ฉันไม่เข้าใจว่านี่จะเป็นคำตอบที่ยอมรับได้อย่างไรเพราะมันไม่ได้ตอบคำถามแม้ว่ามันจะเป็นความคิดเห็นที่น่าสนใจมากก็ตาม
qdii

16
@Mauris: มีคนแก้ไขคำถามและเลื่อนคำถามย่อยไปที่ชื่อคำถาม ชื่อเดิมนั้นแย่มาก แต่คำถามของ OP นั้นเกี่ยวกับวิธีการทำงานของโค้ดแฮ็กบิตที่อ้างถึงและ "มันไม่ได้อย่างน้อยก็ไม่สามารถพกพาได้และนี่คือเหตุผล" เป็นคำตอบที่มีประโยชน์
R .. GitHub STOP HELPING ICE

12
อ่าเข้าใจแล้ว น่าเศร้าที่คำถามนี้ปรากฏในผลการค้นหาของ Google สำหรับ"What is CHAR_BIT?" สูงมาก แม้ว่านั่นจะไม่ใช่คำถามเดิมก็ตาม :( จากคำอธิบายของคุณฉันเข้าใจว่าทำไมคุณถึงเขียนคำตอบนี้ แต่สำหรับคนรุ่นหลังอาจมีประโยชน์มากกว่าที่จะ (ก) ลบคำตอบของคุณและเขียนใหม่เป็นความคิดเห็นสำหรับคำถามเพื่อให้ @ AraK ปรากฏอยู่ด้านบนหรือ (b) แก้ไขคำตอบของคุณเพื่อให้ตอบโจทย์ปัจจุบันของคำถาม
ลินน์

1
เนื่องจากความตั้งใจที่แตกต่างกันระหว่างคำถามดั้งเดิมของ OP และการตีความของบรรณาธิการดูเหมือนว่าลักษณะของคำขอเดิมจะถูกเปลี่ยนโดยไม่สมัครใจ แม้ว่าทั้งสองคำถาม (ต้นฉบับและที่แก้ไข) จะมีประโยชน์ แต่ความแตกต่างนี้จำเป็นต้องได้รับการแก้ไข ตอนนี้ฉันสอบถาม: สามารถเพิ่มคำตอบนี้ในวิกิได้หรือไม่? สิ่งนี้อาจช่วยผู้ที่กำลังค้นหาข้อมูลประเภทนี้แม้ว่าจะไม่เกี่ยวข้องกับคำถามเดิมก็ตาม หลังจากนั้นคำถามสามารถแก้ไขได้อีกครั้งเพื่อให้เหมาะสมกับคำขอเดิมของ dato datuashvili แค่ผู้อ่านที่ห่วงใย ...

2
ฉันเพิ่งดูประวัติของคำถามนี้และคำถามเดิมไม่ได้ถามว่าโค้ดทำงานอย่างไร คำถามที่บรรณาธิการเลื่อนตำแหน่งเป็นคำถามจริงเพียงคำถามเดียวในนั้น
plugwash

230

CHAR_BITcharเป็นจำนวนบิตใน ทุกวันนี้สถาปัตยกรรมเกือบทั้งหมดใช้ 8 บิตต่อไบต์ แต่ก็ไม่ได้เป็นเช่นนั้นเสมอไป เครื่องรุ่นเก่าบางเครื่องเคยมีไบต์ 7 บิต

สามารถพบได้ใน<limits.h>.


3
DSP บางตัวมี 10 บิตหรือมากกว่านั้น
Juri Robl

64
C ต้องการCHAR_BIT>=8และอนุญาตค่าที่ใหญ่กว่ามากสำหรับ DSP ซึ่งมีขนาดประเภทเดียวมักเป็น 32 บิต POSIX CHAR_BIT==8ต้อง โดยทั่วไปแล้วคุณสามารถสมมติใด ๆ ที่ผู้ใช้หลาย / multitasking สถาปัตยกรรมเซิร์ฟเวอร์เชิงโต้ตอบหรือการใช้งานที่มุ่งเน้นการมีโอกาสที่จะถูกเชื่อมต่อกับอินเทอร์เน็ตหรือการสับเปลี่ยนข้อมูลเกี่ยวกับใจกับโลกภายนอกใด ๆ CHAR_BIT==8ที่มี
R .. GitHub STOP HELPING ICE

6
@caf: ไม่ C99 ต้องการประเภทint8_tและuint8_tมีอยู่จริง ดังนั้นจึงมีประเภทของความกว้าง 8 เนื่องจากsizeofประเภทใด ๆ จะต้องเข้ากันได้sizeof charจริงsizeof int8_tต้องเป็น 1 ดังนั้นCHAR_BIT == 8. ฉันได้เขียนบางสิ่งเกี่ยวกับการเชื่อฟังที่นี่: gustedt.wordpress.com/2010/06/01/how-many-bits-has-a-byte
Jens Gustedt

22
@Jens Gustedt: โปรดอ้างอิงส่วนหนึ่งในข้อมูลจำเพาะ C99 ในประเภทจำนวนเต็มความกว้างที่แน่นอนข้อมูลจำเพาะ C99 ระบุว่า "ประเภทเหล่านี้เป็นทางเลือก" (7.18.1.1/3) อย่างไรก็ตามต้องระบุประเภทความกว้างต่ำสุดและความกว้างเร็วที่สุด
jamesdlin

3
@jamesdlin & caf: ขอโทษที่ฉันผสมสิ่งต่างๆ ใช่ฉันต้องการที่อ้างจริงมาจาก POSIX stdint.hสำหรับ ดังนั้นจึงจำเป็นและยังถูกทำเครื่องหมายเป็นส่วนขยายของมาตรฐาน ISO Cโดยไม่ต้องอ้างอิงถึงเวอร์ชันใดมาตรฐานหนึ่ง ความผิดฉันเอง.
Jens Gustedt

2

พยายามตอบทั้งคำถามที่ชัดเจน (CHAR_BIT คืออะไร) และคำถามโดยนัย (วิธีนี้ได้ผลอย่างไร) ในคำถามเดิม


ถ่านใน C และ C ++ แสดงถึงหน่วยความจำที่เล็กที่สุดที่โปรแกรม C สามารถระบุได้ *

CHAR_BIT ในภาษา C และ C ++ แทนจำนวนบิตในอักขระ ต้องมีค่าอย่างน้อย 8 เสมอเนื่องจากข้อกำหนดอื่น ๆ ในประเภทถ่าน ในทางปฏิบัติในคอมพิวเตอร์เอนกประสงค์สมัยใหม่ทั้งหมดนั้นมีค่าเท่ากับ 8 แต่ระบบประวัติศาสตร์หรือผู้เชี่ยวชาญบางระบบอาจมีค่าสูงกว่า

Java ไม่มีความเท่าเทียมกันของ CHAR_BIT หรือ sizeof จึงไม่จำเป็นต้องใช้เนื่องจากประเภทดั้งเดิมทั้งหมดใน Java มีขนาดคงที่และโครงสร้างภายในของอ็อบเจ็กต์จะทึบแสงสำหรับโปรแกรมเมอร์ หากแปลโค้ดนี้เป็น Java คุณสามารถแทนที่ "sizeof (int) * CHAR_BIT - 1" ด้วยค่าคงที่ 31

ในรหัสเฉพาะนี้จะถูกใช้เพื่อคำนวณจำนวนบิตใน int โปรดทราบว่าการคำนวณนี้ถือว่าประเภท int ไม่มีบิตช่องว่างภายใน

สมมติว่าคอมไพเลอร์ของคุณเลือกที่จะลงนามขยายในการเปลี่ยนแปลงบิตของตัวเลขที่ลงชื่อและสมมติว่าระบบของคุณใช้การแทนค่า 2s สำหรับจำนวนลบซึ่งหมายความว่า "MASK" จะเป็น 0 สำหรับค่าบวกหรือศูนย์และ -1 สำหรับค่าลบ

ในการลบล้างหมายเลขเสริมสองเราจำเป็นต้องดำเนินการในระดับบิตไม่ใช่แล้วเพิ่ม เท่า ๆ กันเราสามารถลบหนึ่งแล้วลบออกเป็นบิตได้

อีกครั้งสมมติว่าการแทนค่าสองส่วนเสริม -1 จะแสดงโดยทุกคนดังนั้นเอกสิทธิ์หรือด้วย -1 จึงเทียบเท่ากับการปฏิเสธแบบบิต

ดังนั้นเมื่อ v เป็นศูนย์จำนวนจะถูกปล่อยให้อยู่คนเดียวเมื่อ v เป็นหนึ่งมันจะถูกลบล้าง

สิ่งที่ต้องระวังคือการเซ็นชื่อล้นใน C และ C ++ เป็นพฤติกรรมที่ไม่ได้กำหนด ดังนั้นการใช้ ABS นี้กับค่าที่เป็นลบมากที่สุดจึงนำไปสู่พฤติกรรมที่ไม่ได้กำหนด สิ่งนี้สามารถแก้ไขได้โดยการเพิ่มการร่ายเพื่อให้บรรทัดสุดท้ายของโปรแกรมถูกประเมินเป็น int ที่ไม่ได้ลงนาม

* ซึ่งโดยปกติแล้วจะไม่เหมือนกับหน่วยความจำที่เล็กที่สุดที่ฮาร์ดแวร์สามารถระบุได้ การใช้งานสามารถรวมหน่วยความจำฮาร์ดแวร์แอดเดรสหลายหน่วยเข้าเป็นหน่วยเดียวของหน่วยความจำโปรแกรมแอดเดรสหรือแยกหน่วยความจำแอดเดรสฮาร์ดแวร์หนึ่งหน่วยออกเป็นหน่วยความจำที่สามารถเพิ่มโปรแกรมได้หลายหน่วย

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