unsigned replace_byte(unsigned x, int i, unsigned char b);
思路1,将 x 那个字节找到,然后移位到最后,更改为b,再移位回去。但是要加上 x 之前的后面字节,后面字节加上去这是个难点;
思路2,将 b 左移到与 x 中的字节 i 对应的位置,然后替换掉。
想了有半天时间了= =。
看了答案的解法,是将 b 左移到对应位置。然后将原来的 x 去掉对应 i 位置的字节,然后再加上这个 b 即可。b左移这个简单,就是 b << ( (sizeof(int)-i)>>3)。
关键是 x 如何去掉对应字节的值。设置掩码 然后用 x & mask,例如 x=0x12 34 56 78,则 x & mask = 0x12 00 56 78,那么这个掩码就应该是 ff 00 ff ff,如何得到这样的掩码。它的反 是 0x 00 ff 00 00 ,只需要将 0xff 左移这么多字节即可。
步骤:
①设置掩码 mask = 0xff
②掩码左移到对应字节位置 mask << ( (sizeof(int)-i) << 3),结果为 0xff 00 00
③掩码取反 ~mask,结果为 0xff 00 ff ff
④去掉x对应位置字节 x & ~mask,结果为 0x12 00 56 78
⑤b左移到对应字节为止 b << ( (sizeof(int)-i) << 3),结果为 0xAB 00 00
⑥将④和⑤步骤加和,④ | ⑤ = (x & ~mask) | (b...)
代码
#include
#include
unsigned replace_byte(unsigned x, int i, unsigned char b){
if(i < 0){
printf("error");
return x;
}
if(i > sizeof(unsigned)-1){
printf("error");
return x;
}
unsigned mask = ((unsigned)0xFF) << (i << 3);
unsigned pos_byte = ((unsigned)b) << (i << 3);
return (x & ~mask) | pos_byte;
}
int main(){
unsigned rep_0 = replace_byte(0x12345678, 2, ,0xAB);
return 0;
}
2.61
写一个C表达式,在下列描述的条件下产生 1,而在其他情况下得到 0.假设 x 是int 类型。
A. x 的任何位 都等于 1.
x & 0xffffffff
! ~x
解释:如果x都为1,假设 1111 1111 那么 ~x 就是 0000 0000,然后 ! 是逻辑运算符,输出结果为 true(1)。
B. x 的任何位 都等于 0.
x & 0x00000000
!x
解释:若 x 全为0,如 0000 0000 那么 ! 00000000 输出 1.
C. x 的最低有效字节中的位都等于 1
(x & 0xff) && 0xff
!~(x | ~0xff)
0xff = 0x0000 00FF ,~0xFF就是 0xFFFF FF00, 如 x=0x0000 00ff,则 x | ~0xFF 就是 0xffff ffff 为全 1,之后操作跟如上道理一样。
D. x 的最高有效字节中的位 都等于 0
(x >> 3 & 0xff) && 0x00
如何取最高字节?x >> 24, 24怎么得来的。sizeof(int)-1 << 3 = 3 << 3 = 3 * 8 = 24
!(x >> (sizeof(int)-1) << 3) & 0xff)
如 x = 0x0012 3456,则 x >> 24 为 0x00, 0x00 & 0xff = 0x00, 之后 ! 0x00,就是1啦。
2.62
编写一个函数 int_shifts_are_arithmetic(),在对 int 类型的数使用 算数右移 的机器上运行时这个函数 生成 1,而其他情况生成 0.
你的代码应该可以运行在任何字长的机器上。在几种机器上运行你的代码。
思路:
算数右移,正数无法判断。只能是负数,当执行算数右移的时候,高位补出来的数字都是 1,则说明该移位是 算术右移。
发现,直接判断最高位有效字节是否会变大,就可以判断是算数移位还是逻辑移位。变小肯定是逻辑移位。
分别取 移位前 移位后 的最高有效字节。