การหมุนขวาของ Bits ใน C
ฉันกำลังทำแบบฝึกหัด 2-8 ใน K&R ซึ่งขอให้เราเขียนฟังก์ชันrightrot(int x, int n)
เพื่อให้บิตทั้งหมดx
ถูกเลื่อน n ครั้งไปทางขวาโดยบิตที่หลุดจากปลายด้านขวาจะปรากฏขึ้นอีกครั้งที่ด้านซ้ายสุด
นี่คือวิธีแก้ปัญหาที่ฉันพยายามซึ่งฉันเปลี่ยนทีละบิตทีละรายการ:
int rightrot(int x, int n)
{
int i, rmb;
for(i = 0; i < n; ++i)
{
// get right-most bit
rmb = x & 1;
// shift 1 to right
x = x >> 1;
// if right-most bit is set, set left-most bit
if (rmb == 1)
x = x | (~0 ^ (~0 >> 1) );
}
return x;
}
เมื่อผมดำเนินการrightrot(122, 2)
ผมคาดว่าจะได้รับ94
ตั้งแต่122
เป็น1111010
และเป็น94
1011110
แต่ฉันได้รับที่เกิดขึ้นจะ30
0011110
เห็นได้ชัดว่าวิธีการตั้งค่าบิตด้านซ้ายสุดของฉันไม่ได้ผลตามที่ฉันคาดไว้ มีใครเห็นข้อผิดพลาดที่ชัดเจนหรือไม่? ฉันแค่เรียนรู้เกี่ยวกับการจับบิตและสิ่งที่คล้ายกัน
หมายเหตุ:ฉันได้รับเทคนิคในการตั้งค่าบิตซ้ายสุดจากโพสต์นี้
คำตอบ
มาวิเคราะห์(~0 ^ (~0 >> 1) )
กัน:
~0
เป็น-1
~0 >> 1
อีกครั้ง-1
ถ้าบิตเครื่องหมายถูก1
เลื่อนจะเติมบิตใหม่ด้วย1
s
-1 ^ -1
คือ0
.
x = x | 0
คือx
.
วิธีแก้ปัญหาคือคุณควรใช้ประเภทข้อมูลที่ไม่ได้ลงชื่อหากคุณต้องการทำ bitoperations
ดังนั้นคุณควรใช้บรรทัดx = x | (~0u ^ (~0u >> 1) );
เพื่อหลีกเลี่ยงปัญหาอื่น ๆ พารามิเตอร์x
ควรเป็นunsigned int
เช่นกัน
https://ideone.com/7zPTQk