/*
135. * bitAnd - x&y using only ~ and |
136. * Example: bitAnd(6, 5) = 4
137. * Legal ops: ~ |
138. * Max ops: 8
139. * Rating: 1
140. */
141.int bitAnd(int x, int y) {
142.
143. return ~(~x|~y);
144.}
这是第一个函数,看描述是要我们仅使用~和|实现&的功能。还记得离散数学上学的摩根定律吗,x&y = ~(~x|~y) ,所以第一个是比较简单的。
/*
146. * getByte - Extract byte n from word x
147. * Bytes numbered from 0 (LSB) to 3 (MSB)
148. * Examples: getByte(0x12345678,1) = 0x56
149. * Legal ops: ! ~ & ^ | + << >>
150. * Max ops: 6
151. * Rating: 2
152. */
153.int getByte(int x, int n) {
154.
155. return x>>(n<<3)&0xff;
156.
157.}
第二个函数,实现向返回第几字节的操作。需要知道的是两个数字占一个字节。而八个数字即是四个字节,双字。所以n只能从0到3取。第0位是最低位,例子里即是78,3为最高位,存的是12,以此类推。所以要返回第n位的数字,我们需要做的是右移挤掉比n低的数位,并且忽略掉比n高的数位。所以我们先做右移操作,需要注意的是移位的时候是按照二进制移位的,所以要先将n乘8,即n<<3,然后再右移。右移之后我们需要的数字就是最低位了,再和0xff做与运算,就可以把高位的数位全部忽略掉。
/*
159. * logicalShift - shift x to the right by n, using a logical shift
160. * Can assume that 0 <= n <= 31
161. * Examples: logicalShift(0x87654321,4) = 0x08765432
162. * Legal ops: ! ~ & ^ | + << >>
163. * Max ops: 20
164. * Rating: 3
165. */
166.int logicalShift(int x, int n) {
167.
168. return (x>>n)&(~((0x1<<31)>>n<<1));
169.}
第三个函数,实现逻辑右移。计算机在右移的时候会对有符号数进行算术右移(补齐最高有效位),对无符号数进行逻辑右移。这个函数要实现的是无条件的逻辑右移,也即我们需要做的是将右移的数与0x00…11做与运算,其中0的个数等同于右移位数。所以我们需要的是~(1<<31)>>n<<1[不能使用-号,所以不是n-1],所以结果是(x>>n)&(~(1<<31)>>n<<1).
/*
171. * bitCount - returns count of number of 1's in word
172. * Examples: bitCount(5) = 2, bitCount(7) = 3
173. * Legal ops: ! ~ & ^ | + << >>
174. * Max ops: 40
175. * Rating: 4
176. */
177. /*
178. **参考《CSAPP深入理解计算机系统》例3.50解答
179. */
180.int bitCount(int x) {
181. int c;
182. c=(x&0x55555555)+(x>>1&0x55555555);
183. c=(c&0x33333333)+(c>>2&0x33333333);
184. c=(c&0x0f0f0f0f)+(c>>4&0x0f0f0f0f);
185. c=(c&0x00ff00ff)+(c>>8&0x00ff00ff);
186. c=(c&0x0000ffff)+(c>>16&0x0000ffff);
187. return c
}
第四题要求返回二进制数中1的个数。参考深入理解3.50。我认为这个函数的难度较大,我参考了这个论坛的内容