【全文大纲】 : https://blog.youkuaiyun.com/Engineer_LU/article/details/135149485
1 . 前言总结
当在后台循环判断变量时,要留意编译器把变量送进寄存器变量中判断引发的细节问题
2 . 问题现象
在判断时,编译把变量放到内部R0-Rx寄存器变量,而MDK是32位平台,所以 R0-Rx寄存器变量 取反后为0xFFFFFF55,因此与0x00000055不相等,导致判断错误,程序逻辑异常
u8 i = 0x55;
u8 j = 0xaa;
if (i == ~j) {
return 1;
}
return 0;
3 . 解决思路
为了解决以上问题,可在取反前缀加强转转换告诉编译器这里无论平台多少位,后续转成汇编都要以8位范围来判断
u8 i = 0x55;
u8 j = 0xaa;
if (i == (u8)~j) {
return 1;
}
return 0;
4 . 细节扩展
除了上述情况,还有各种操作符使变量隐式转换,例如下述判断方式,结果return 0; 原因是j的结果左移后为0x00000000,因为编译有优化,这些判断都基于缓存来判断实现,u8 << 16,如果是Keil平台则超出了默认的16位范围,因此超出范围,所以为0x00000000,处理方法也是制转换j为u32, (u32)j<<16 ,这样编译下来,j就为32bit变量,编译器判断比较时就按u32来判断了
u8 i = 0x550000;
u8 j = 0x55;
if (i == (j<<16)) {
return 1;
}
return 0;
5 . 总结
优秀的代码,在任何优化下,基本很少影响正常运行 (不排除极端优化导致的逻辑问题),一般考虑定义时的类型,不能完全相信编译器定义变量时的类型,嵌入式要考虑底层硬件平台的优化转换导致的类型差异,因此我们要想保证一段代码是我们想要的逻辑,就告诉编译器这里要做成怎样的逻辑,不可自行干预影响。
技术交流群 : 745662457
群内专注 - 问题答疑,技术研究