[C语言] 嵌入式C大师请进(MISRA警告处理)

[复制链接]
1610|27
 楼主| 791314247 发表于 2021-1-19 11:43 | 显示全部楼层 |阅读模式
本帖最后由 791314247 于 2021-1-19 17:26 编辑

如下程序:
unsigned int a;
unsigned int b;
signed int c;
function(void)
{
    c = a-b;  /* 违反了MISRA规则10.8 */
}
如上程序,c = a-b违反了MISRA规则10.8:

意思是复合表达式的值不能转换为不同类型的值或者转换为了更广泛的类型
请问如何最方便的优化掉这个警告?不想再加中间变量了
我试过以下几个方案:

1,c = (signed int)(a-b);   /* 这个肯定不行,还是报警 */

2,c = (signed int)a - (signed int)b;   /* 这个在a或者b的值很大的时候是否有风险呢 */

补充:第2个方案是不行的,比如当b=0XFFFFFFFF的时候,b会被解释成-1,那么a - -1=a+1,和预期是不同的结果


本帖子中包含更多资源

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

×
ayb_ice 发表于 2021-1-19 13:03 | 显示全部楼层
(unsigned int)c = a-b;
ayb_ice 发表于 2021-1-19 13:03 | 显示全部楼层
(unsigned int)c = a-b;
 楼主| 791314247 发表于 2021-1-19 13:59 | 显示全部楼层
ayb_ice 发表于 2021-1-19 13:03
(unsigned int)c = a-b;

老哥,您在逗我吗
xyz549040622 发表于 2021-1-19 14:41 来自手机 | 显示全部楼层
791314247 发表于 2021-1-19 13:59
老哥,您在逗我吗

可以试试?
dirtwillfly 发表于 2021-1-19 15:00 | 显示全部楼层
不考虑应用场景,单纯谈编码规则没有意义。
像这种情况,我可能直接把a、b定义成signed int类型
 楼主| 791314247 发表于 2021-1-19 15:13 | 显示全部楼层

类型转换只能在等号右边
 楼主| 791314247 发表于 2021-1-19 15:15 | 显示全部楼层
dirtwillfly 发表于 2021-1-19 15:00
不考虑应用场景,单纯谈编码规则没有意义。
像这种情况,我可能直接把a、b定义成signed int类型 ...

应用场景就是a b必须是一个正整数,c是a b的差值,如果把a b解释成带符号的是有问题的,比如3 - 2  和3 - -2结果是不同的
icecut 发表于 2021-1-19 15:20 | 显示全部楼层
a>b?int(a-b):int(-(b-a))

评论

不行啊老哥 ,MISRA规定表达式的结果不能转换为不同的类型,int(a-b)和c的类型还是不一样,还是违反了规则  发表于 2021-1-19 15:33
dirtwillfly 发表于 2021-1-19 15:55 | 显示全部楼层
791314247 发表于 2021-1-19 15:15
应用场景就是a b必须是一个正整数,c是a b的差值,如果把a b解释成带符号的是有问题的,比如3 - 2  和3 - ...

正整数也要看取值范围,如果取值范围在signed int的正值范围,完全没问题
ayb_ice 发表于 2021-1-19 16:04 | 显示全部楼层
791314247 发表于 2021-1-19 13:59
老哥,您在逗我吗

标准C89肯定是可以的
fcccc 发表于 2021-1-19 16:41 | 显示全部楼层
本帖最后由 fcccc 于 2021-1-19 17:21 编辑

用一个同类型型有符号变量接收无符号变量的差是错误的操作.
举个例子:

unsigned short  a = 0xFFFF,b = 0;
signed short c = 0;
c = a-b ;

结果c= 0xFFFF= -1; 结果是错误的.




两个16bit数相减因为涉及到符号问题,包含的信息量增加了,原来的16bit已经存不下多出来的符号位;
因为:

a = 0;
b = 1;
c = a-b;
//c也 = 0xFFFF = -1;也会得到相同结果!
如何区分这两种情况?

如果是加法你一般会想到用一个更大的数存放结果,因为会溢出;
减法和加法是等价的;

必须转换成更大的有符号变量,或者使用中间变量存储符号;

要了解MISRA-C警告的本质,就知道怎么处理了.

评论

@fcccc :有道理  发表于 2021-1-20 10:34
@791314247 :0xFFFF可能应该是-1;也可能就是65535,需要区别他俩.  发表于 2021-1-19 19:21
@791314247 :多出来一个符号位你没地方放.  发表于 2021-1-19 19:17
@791314247 :0-65535呢?  发表于 2021-1-19 19:16
其实我仔细想了以下,错误的本质是2个unsigned short型的数据的差最大是0XFFFF,也就是65535,而相同类型的singned short型的数据取值范围却是-32768~32767,最大只有32767,根本就不能接收65535,所以我觉得这才是错误的本质  发表于 2021-1-19 18:59
讲解的很明白很清晰  发表于 2021-1-19 17:41
老哥,稳,强  发表于 2021-1-19 17:23
雪山飞狐D 发表于 2021-1-19 18:01 | 显示全部楼层
  uint32_t   a
  uint32_t   b
  int64_t   c

  c=(int64_t)a- (int64_t)b;

评论

@雪山飞狐D :上面说了减法和加法是等价的,必须使用大一号的数据接收结果;  发表于 2021-1-19 19:37
@雪山飞狐D :有符号是错误的;short a=32767,b=-2,c = 0; c = a-b = 32769!  发表于 2021-1-19 19:36
@791314247 :那就通通用有符号类型就好了,只要数据不超过有符号范围,实在超过,就只能自定义64位运算了  发表于 2021-1-19 19:13
这样是可以的,但可惜编译器最大是32位的  发表于 2021-1-19 18:38
fcccc 发表于 2021-1-19 19:10 | 显示全部楼层
在嵌入式软件设计中,变量的声明应该坚最小类型原则;
因为对于一个8位或者32位MCU处理int64_t类型的计算需要花费更多时钟周期;
因为寄存器的位宽有限,需要分几次加载长度超过位宽的变量.
如果能确定short类型能放得下,就不要用int;我用short类型举例也是这个意思;
ayb_ice 发表于 2021-1-20 11:32 | 显示全部楼层
这种情况本身就是可能产生情况,结果溢出,符号位发生变化,这是程序员本身应该考虑的事
xjl85 发表于 2021-1-22 10:07 | 显示全部楼层
这不就是个类型转换问题嘛
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

24

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部