前几天在调路由下发的时候碰到一个很诡异的错误,计算机执行的结果跟我手算的结果就是对不到一块儿,当时的代码是这样的
ina.ifra_mask.sin_addr.s_addr = htonl(~(0xffffffffU >> prefix_len));
其中prefix_len的值为32。自己预想的结果应该是右移32bit让括号内变为0,然后在取反变成全1,最后调整调整字节序后结果也是全为1。但是很无奈,计算机算出来的结果就是0。
在纠结了半小时,突然想到以前看过一篇关于Intel的移位指令存在的缺陷的文章,http://blog.chinaunix.net/uid-23629988-id-127318.html这是文章的链接。这篇文章写了右移指令在碰到计数操作数大于31时就会发生意料之外的结果,在这里我想说不仅仅是右移有这个问题,左移同样存在这个问题。
下面这段代码是我的测试代码:
int prefix_len = 32;
int y = htonl(~(0xffffffffU >> prefix_len));
printf("y is %x\n", y);
通过gcc编译产生一个可执行文件,执行的结果是:
当把prefix_len改为0-31时,移位是正常的,如:
咱们在来试试prefix_len=33和prefix_len=1的情况,
先是=33:
然后是=1:
所以以后在试用移位指令的时候自己多留个心眼吧,别超范围了。