搜索
bottom↓
回复: 30

stm32 无符号char,如果不初始化,右移8位后,值不一定是0

[复制链接]

出0入0汤圆

发表于 2020-6-3 20:56:23 | 显示全部楼层 |阅读模式
keil MDK 编译,
unsigned char k , b ;
................
b = k>>8;
这时b 可能不是0。什么原因?

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2020-6-3 21:03:55 | 显示全部楼层
k没有初始化,试试赋个0xFF

出0入4汤圆

发表于 2020-6-3 21:15:01 | 显示全部楼层
你降低下编译器优化等级试试

出0入0汤圆

 楼主| 发表于 2020-6-3 21:40:15 | 显示全部楼层
cumt_123456 发表于 2020-6-3 21:15
你降低下编译器优化等级试试

降到 0 级也是一样。
只要先赋个值 ,就不出错了

出0入984汤圆

发表于 2020-6-3 21:47:01 | 显示全部楼层
调试模式汇编跟一下看看编译成什么指令了

出0入0汤圆

 楼主| 发表于 2020-6-3 21:58:18 | 显示全部楼层
gmajvfhpa 发表于 2020-6-3 21:40
降到 0 级也是一样。
只要先赋个值 ,就不出错了
  1.    611:                                                k=0;
  2. 0x080188CE 2700      MOVS     r7,#0x00
  3.    612:                                                for(j=0;j<x;j++)
  4.    613:                                                {
  5. 0x080188D0 2400      MOVS     r4,#0x00
  6. 0x080188D2 E01C      B        0x0801890E
  7.    614:                                                 k= k>>1;
  8. 0x080188D4 107F      ASRS     r7,r7,#1
复制代码


查看到的汇编代码,K不初始化时,R7的值就不确定。8位 的K 右移。并不是只移动R7的低8位,而是把R7高位的数据移入低8位中,所以出现不想要的结果。
但这样的话,又不符合 ”8位无符号 右移,左边补0“  这种说法

出15入178汤圆

发表于 2020-6-3 22:07:09 | 显示全部楼层
GCC试了下没这个问题,字节左移赋值后是零。

出0入0汤圆

 楼主| 发表于 2020-6-3 22:14:04 | 显示全部楼层
2nd 发表于 2020-6-3 22:07
GCC试了下没这个问题,字节左移赋值后是零。

跟踪结果是没补始化时 R7=0x07070707,右移一位后是0x03838383

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入442汤圆

发表于 2020-6-3 22:22:01 来自手机 | 显示全部楼层
gmajvfhpa 发表于 2020-6-3 22:14
跟踪结果是没补始化时 R7=0x07070707,右移一位后是0x03838383

那这是mdk的bug了,数据类型被自动扩展了但是没有后续的掩码工作。gcc如果用byte类型会导致汇编里大量的shl 24,shr 24操作来移除高位全部0。所以arm之类的一般都强烈建议完全基于32位整型来计算,避免数据的额外处理步骤。

出1310入193汤圆

发表于 2020-6-4 08:08:56 | 显示全部楼层
32位mcu  处理32位数据最为拿手   省时省力     处理8位数据反而耗时吃力还容易出错

出0入21汤圆

发表于 2020-6-4 08:24:15 | 显示全部楼层
32位宽,向右移,会不会把bit8-15的随机数移过来了,你向左移8位试试.

出0入0汤圆

发表于 2020-6-4 09:29:30 | 显示全部楼层
为什么老是纠结这些不规范的写法是什么表现呢?
怎么表现都是正常的,换个编译器可能就是不同的结果。
如果想满足好奇心,建议关闭编译器的自动整型提升看看,可能会得到你想要看到的结果。

出0入0汤圆

发表于 2020-6-4 10:32:12 | 显示全部楼层
这里b不是0又如何呢,真正用的时候,会帮你变成0的,编译器都很聪明,会延迟生效

出10入0汤圆

发表于 2020-6-4 10:36:39 | 显示全部楼层
本帖最后由 goodjob2 于 2020-6-4 10:40 编辑

右移8位是个什么操作?不会溢出吗?你这个UCHAR本身才8位啊

出0入0汤圆

发表于 2020-6-4 12:08:45 | 显示全部楼层
wye11083 发表于 2020-6-3 22:22
那这是mdk的bug了,数据类型被自动扩展了但是没有后续的掩码工作。gcc如果用byte类型会导致汇编里大量的s ...

关于这点,UXTB它不香吗……

出0入0汤圆

发表于 2020-6-4 15:25:52 | 显示全部楼层
为什么就没有人想下这个没有初始化的变量是个什么值呢

出4375入62汤圆

发表于 2020-6-4 16:01:37 | 显示全部楼层
楼主试试定义为全局变量不初始化

出0入4汤圆

发表于 2020-6-4 17:37:52 | 显示全部楼层
那你就初始化一下会死啊

出870入263汤圆

发表于 2020-6-4 19:34:09 | 显示全部楼层
你这个问题条件不足,要看k,b是局部变量还是全局静态变量。
如果是局部变量,k,b就是不确定的;全局静态变量的话会被放在bss段,c启动代码把它们初始化成0。

出0入0汤圆

 楼主| 发表于 2020-6-5 08:07:31 | 显示全部楼层
armstrong 发表于 2020-6-4 19:34
你这个问题条件不足,要看k,b是局部变量还是全局静态变量。
如果是局部变量,k,b就是不确定的;全局静态 ...

K是局部变量。在8位机上 unsigned char  右移 左边是补0,但现在32位机上,在K不初始化的情况下右移,左边不一定是补0.

出10入0汤圆

发表于 2020-6-5 08:41:11 | 显示全部楼层
gmajvfhpa 发表于 2020-6-5 08:07
K是局部变量。在8位机上 unsigned char  右移 左边是补0,但现在32位机上,在K不初始化的情况下右移,左 ...

你一个8位数据,最多移7位,你移8位是做什么?1000 0000 >>7 =  0000 0001

出0入0汤圆

发表于 2020-6-5 11:25:57 | 显示全部楼层
中途没有赋值的,定义的时候就要初始化。

出90入0汤圆

发表于 2020-6-5 14:08:20 | 显示全部楼层
32位CPU,用32位数据最好。

出0入0汤圆

发表于 2020-6-16 16:13:20 | 显示全部楼层
纠结这个问题没有什么意义

出0入12汤圆

发表于 2020-6-16 20:46:07 | 显示全部楼层
C 语音里面未定义行为,一个 8 位的数据右移 8 位之后应该是啥?

出0入296汤圆

发表于 2020-6-16 22:41:43 | 显示全部楼层
局部变量未初始化的时候,编译器是没有义务保证他的值为某一个确定的数值的。这个可不是编译器BUG。不要与自己
预期不符合就说是编译器bug。

出5入14汤圆

发表于 2020-6-16 23:11:38 来自手机 | 显示全部楼层
wye11083 发表于 2020-6-3 22:22
那这是mdk的bug了,数据类型被自动扩展了但是没有后续的掩码工作。gcc如果用byte类型会导致汇编里大量的s ...

我也觉得是BUG,不符合C的标准用法。

出5入14汤圆

发表于 2020-6-16 23:13:57 来自手机 | 显示全部楼层
Gorgon_Meducer 发表于 2020-6-16 22:41
局部变量未初始化的时候,编译器是没有义务保证他的值为某一个确定的数值的。这个可不是编译器BUG。不要与 ...

不管是否初始化,右移首位补零好像是标准C的做法吧?当然我并不确定C里是否有明确的说明。

出0入0汤圆

 楼主| 发表于 2020-6-17 11:32:10 | 显示全部楼层
Gorgon_Meducer 发表于 2020-6-16 22:41
局部变量未初始化的时候,编译器是没有义务保证他的值为某一个确定的数值的。这个可不是编译器BUG。不要与 ...

可能我说的不够清楚。其实问题 是:  一个不确定值的 unsigned char 数,右移一位后,首位不一定是补0

出0入296汤圆

发表于 2020-6-17 20:52:40 | 显示全部楼层
gmajvfhpa 发表于 2020-6-17 11:32
可能我说的不够清楚。其实问题 是:  一个不确定值的 unsigned char 数,右移一位后,首位不一定是补0 ...

给你这么一说,的确是编译器在这里欠考虑。
因为arm compiler 5一般是先进行ALU操作,在赋值给别的变量前才会用一条专门指令去把寄存器长度截取为uint8_t。
你这个例子高概率的,a直接就是在通用寄存器页里分配的,按照先ALU运算,后截取的步骤,Rx bit7以上的值已经影响bit0~bit7了,然后才进行长度截取,已经于事无补了——考虑到你保存的结果还是在a里,编译器估计都不会进行长度截取……

你arm compiler 5版本是多少?优化等级是多少?
尝试过arm compiler 6么?arm compiler 5已经停止维护了,即便有问题也不会修复了。

出0入296汤圆

发表于 2020-6-17 20:54:43 | 显示全部楼层
EMC菜鸟 发表于 2020-6-16 23:13
不管是否初始化,右移首位补零好像是标准C的做法吧?当然我并不确定C里是否有明确的说明。 ...

我以为你们说的是未初始化的变量初始值的问题。真没注意到这里移位非0的问题。
不过我知道编译器会怎么做,所以判断下来,我知道为什么会有这个问题。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 22:17

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表