最近被坑惨了,根源于 1 << 15 ,1 << 16 的值是多少的问题。
之前写了一款产品,有个句子
int a,b;
a |= 1 << b;
当时 b 的值从 0 到 15,一切都很正常。
后来产品扩展,就改成
Uint32 a
int b
a |= 1 << b
b 的值从 0 到 31。
单台产品运行时,看起来很正常,扩展出来的 a 的高16位能正常得到1,这也是我关注的地方,而低16位目测也正常。
但是将新代码和旧代码放到一起比较,就发现两台产品的运行有差异。尽快很快就定位到这个 1 << b ,因为我知道 1 默认是 int 类型,左移超过15位肯定有异常,但是,我的直觉告诉我,超过15位应该是0,在expression窗口输入 1 << 16 , 1 << 17 ,显示结果也都是 0,所以从理论上,a 的低16位不应该出现异常,应该是搞16位永远得不到 1,而事实上不是这样。
最后发现,当 b 等于 15 时,a 的高16位全是 1 !
当然这也可以理解,1 << 15 = -32768 , 高位对齐的话,a 高位用1填充,我认了。
然后,当 b 等于 16 时,a 的最低位居然又等于 1 !!!
b等于17时,a的第二位等于1!!!!!
问题就是这样,a 在一个周期内,低16位被重复赋值两次,比以前多了一次,所以程序的时间改变了,这种改变肉眼很难立即觉察,只有两台产品放在一起才能注意到。
关于这个问题,相信大侠们有很多真知灼见,欢迎讨论!以上的描述一些细节可能有出入,这两天忙着填坑,填完了才来这里,一些仿真细节可能记错了。
rookiecalf:
是因为隐含类型引起的BUG,1是int型,移位是按16取余的,所以需要对被移数据先确定需要的数据类型(必要时强制类型转换),然后再移位,才不会出现这样的bug
最近被坑惨了,根源于 1 << 15 ,1 << 16 的值是多少的问题。
之前写了一款产品,有个句子
int a,b;
a |= 1 << b;
当时 b 的值从 0 到 15,一切都很正常。
后来产品扩展,就改成
Uint32 a
int b
a |= 1 << b
b 的值从 0 到 31。
单台产品运行时,看起来很正常,扩展出来的 a 的高16位能正常得到1,这也是我关注的地方,而低16位目测也正常。
但是将新代码和旧代码放到一起比较,就发现两台产品的运行有差异。尽快很快就定位到这个 1 << b ,因为我知道 1 默认是 int 类型,左移超过15位肯定有异常,但是,我的直觉告诉我,超过15位应该是0,在expression窗口输入 1 << 16 , 1 << 17 ,显示结果也都是 0,所以从理论上,a 的低16位不应该出现异常,应该是搞16位永远得不到 1,而事实上不是这样。
最后发现,当 b 等于 15 时,a 的高16位全是 1 !
当然这也可以理解,1 << 15 = -32768 , 高位对齐的话,a 高位用1填充,我认了。
然后,当 b 等于 16 时,a 的最低位居然又等于 1 !!!
b等于17时,a的第二位等于1!!!!!
问题就是这样,a 在一个周期内,低16位被重复赋值两次,比以前多了一次,所以程序的时间改变了,这种改变肉眼很难立即觉察,只有两台产品放在一起才能注意到。
关于这个问题,相信大侠们有很多真知灼见,欢迎讨论!以上的描述一些细节可能有出入,这两天忙着填坑,填完了才来这里,一些仿真细节可能记错了。
HH Y:
回复 rookiecalf:
我感兴趣的是,这是 TI 编译器的特性,还是C语言的标准?仿真时expressiong窗口输入 1<<16 显示是 0,算不算一个 bug 呢?
最近被坑惨了,根源于 1 << 15 ,1 << 16 的值是多少的问题。
之前写了一款产品,有个句子
int a,b;
a |= 1 << b;
当时 b 的值从 0 到 15,一切都很正常。
后来产品扩展,就改成
Uint32 a
int b
a |= 1 << b
b 的值从 0 到 31。
单台产品运行时,看起来很正常,扩展出来的 a 的高16位能正常得到1,这也是我关注的地方,而低16位目测也正常。
但是将新代码和旧代码放到一起比较,就发现两台产品的运行有差异。尽快很快就定位到这个 1 << b ,因为我知道 1 默认是 int 类型,左移超过15位肯定有异常,但是,我的直觉告诉我,超过15位应该是0,在expression窗口输入 1 << 16 , 1 << 17 ,显示结果也都是 0,所以从理论上,a 的低16位不应该出现异常,应该是搞16位永远得不到 1,而事实上不是这样。
最后发现,当 b 等于 15 时,a 的高16位全是 1 !
当然这也可以理解,1 << 15 = -32768 , 高位对齐的话,a 高位用1填充,我认了。
然后,当 b 等于 16 时,a 的最低位居然又等于 1 !!!
b等于17时,a的第二位等于1!!!!!
问题就是这样,a 在一个周期内,低16位被重复赋值两次,比以前多了一次,所以程序的时间改变了,这种改变肉眼很难立即觉察,只有两台产品放在一起才能注意到。
关于这个问题,相信大侠们有很多真知灼见,欢迎讨论!以上的描述一些细节可能有出入,这两天忙着填坑,填完了才来这里,一些仿真细节可能记错了。
rookiecalf:
回复 HH Y:
这是属于编译器的特性,编译后代码的执行结果和expression中的不同可以算是两种编译器的差异(expression中的这种直接数据表示是不经过TI编译器的),所以作为开发人员需要尽量避免这样的陷阱