問題描述
2.6 編寫一個函數setbits(x, p ,n, y),該函數傳回對x執行下列操作後的結果值: 将x中從第p位開始的n個(二進制)位設定為y中最右邊n位的值,x的其餘各位保持不變。
Write a function
setbits(x,p,n,y)
that returns
x
with the
n
bits that begin at position
p
set to the rightmost
n
bits of
y,
leaving the other bits unchanged.
知識點複習
1.按位與運算符(&)
參加運算的兩個資料,按二進制位進行“與”運算
運算規則:0&0=0; 0&1=0; 1&0=0; 1&1=1; (兩位同時為“1”,結果才為“1”,否則為0)
例如: 2 & 3
換為二進制:0000 0010 & 0000 0011 = 00000010
是以2 & 3 = 2
(負數按補碼形式參與按位與運算)
2.按位或運算符( | )
參加運算的兩個對象,按二進制位進行“或”運算。
運算規則:0|0=0; 0|1=1; 1|0=1; 1|1=1;(參加運算的兩個對象隻要有一個為1,其值為1)
例如:2 | 3
換位二進制: 0000 0010 | 0000 0011 = 0000 0011
是以2 | 3 = 3
(負數按補碼形式參加按位或運算)
3.按異或運算符( ^ )
參加運算的兩個資料,按二進制位進行“異或”運算。
運算規則:0^0=0; 0^1=1; 1^0=1; 1^1=0;(參加運算的兩個對象,如果兩個相應位為“異”(值不同),則該位結果為1,否則為0)
例如:2 ^ 3
換為二進制:0000 0010 ^ 0000 0011 = 0000 0001
是以2 ^ 3 = 1
異或運算符有一條有趣的性質,自反性:a ^ b ^ b = a
利用這條性質,我們可以不用借助第三個變量,實作兩個數值的交換
例如交換a和b的值:
a = a ^ b;
b = a ^ b;
a = a ^ b;
解釋一下這個代碼:
第一句:令a = a^b
第二局:b=a^b,其中的a用第一句的的等式替換 b = a^b^b=a
第三句同理,a = a^b=a^a^b=b
4.左移運算符(<<)
将一個運算對象的各二進制位全部左移若幹位,左邊的二進制位丢棄,右邊補0
例:0000 0011<<2 = 0000 1100 左移2位,右補0
若左移時舍棄的高位不包含1,則每左移一位,相當于該數十進制下乘以2
5.右移運算符(>>)
将一個數的各二進制位全部右移若幹位,正數左補0,負數左補1,右邊丢棄
操作數每右移一位,相當于該數十進制除以2
左補0 or 補1得看被移數是正還是負
解題步驟
這裡我們直接用一個例子來解釋這道題目:
假設 setbits(93 , 4 , 3 , 211)
93二進制:1 0 1 1 1 0 1
211二進制:1 1 0 1 0 0 1 1
按照題目要求,我們首先要找到93的第4位,也就是橙色标注的數字 1 0 1 1 1 0 1
之後從這一位算起,往右數3位,,也就是橙色标注的數字 1 0 1 1 1 1 1
我們要把上一行中橙色标注的這三位,替換為數字211二進制的最後三位
紅色标注的是211二進制的最後三位:1 1 0 1 0 0 1 1
是以我們的最終目标就是把1 0 1 1 1 1 1 變成 1 0 0 1 1 1 1
代碼如下
#include<stdio.h>
unsigned setbits(unsigned x, int p, int n, unsigned y)
{
return ((x & ~(~(~0 << n) << p+1-n)) | ((~(~0 << n) & y) << p+1-n));
}
int main()
{
printf("%d\n",setbits(93,4,3,211));
return 0;
}
運作結果
歡迎大家關注公衆号:農大CPU