位运算符的陷阱
2019-01-08 本文已影响0人
进击的NULL
背景
今天在写代码计算二叉树根节点右孩子的下标值时,用了如下代码:
/**
* 获取根节点右孩子的的下标值
* @param i
* @return
*/
private int right(int i) {
return i << 1 + 1; // 右孩子为右移一位 + 1
}
当我发现程序结果跟我预期不一样时,调试到此处,发现right(1)返回的结果是4!所以借此记录,只有踩坑的方式补基础知识记忆才比较靠谱!后来我改成了如下代码,就完美解决问题了。
/**
* 获取根节点右孩子的的下标值
* @param i
* @return
*/
private int right(int i) {
return (i << 1) + 1; // 右孩子为右移一位 + 1
}
踩坑之后
遇到上面问题之后,我回顾了下运算符(主要还是位运算符,刻骨铭心)几点tips:
- 怕错就用括号,括号优先级是最高的
- 位运算符优先级没有‘+’(加号优先级高),所以作者上面错了
- 因为还用到了三元运算符的嵌套,所以看了下,发现三元运算符由右向左以(?:)为一对进行运算(我想了下,也是有语言自己设计的道理)。我用到的代码如下,可以不用加括号,但是最开始作者怕错了,还是把括号加上了(this.arr[i] != INF ? true : false)。
/**
* 检查一个下标是否魏越界或者是否存储了实际值
* @param i
* @return 在数组范围内返回true,越界返回false
*/
private boolean isLegal(int i) {
return 1 <= i && i <= this.size() ? this.arr[i] != INF ? true : false : false; // 首先判断数组下标越界与否,在没有越界的基础上还需要判断是否是有效值
}
补一张运算符优先级的图,虽然我知道我不怎么会看,便于参考吧。
运算符的优先级.png