打印
[C语言]

嵌入式C大师请进(MISRA警告处理)

[复制链接]
838|27
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 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;

老哥,您在逗我吗

使用特权

评论回复
5
xyz549040622| | 2021-1-19 14:41 | 只看该作者
791314247 发表于 2021-1-19 13:59
老哥,您在逗我吗

可以试试?

使用特权

评论回复
6
dirtwillfly| | 2021-1-19 15:00 | 只看该作者
不考虑应用场景,单纯谈编码规则没有意义。
像这种情况,我可能直接把a、b定义成signed int类型

使用特权

评论回复
7
791314247|  楼主 | 2021-1-19 15:13 | 只看该作者

类型转换只能在等号右边

使用特权

评论回复
8
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结果是不同的

使用特权

评论回复
9
icecut| | 2021-1-19 15:20 | 只看该作者
a>b?int(a-b):int(-(b-a))

使用特权

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

正整数也要看取值范围,如果取值范围在signed int的正值范围,完全没问题

使用特权

评论回复
11
ayb_ice| | 2021-1-19 16:04 | 只看该作者
791314247 发表于 2021-1-19 13:59
老哥,您在逗我吗

标准C89肯定是可以的

使用特权

评论回复
12
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警告的本质,就知道怎么处理了.

使用特权

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

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

使用特权

评论回复
评论
fcccc 2021-1-19 19:37 回复TA
@雪山飞狐D :上面说了减法和加法是等价的,必须使用大一号的数据接收结果; 
fcccc 2021-1-19 19:36 回复TA
@雪山飞狐D :有符号是错误的;short a=32767,b=-2,c = 0; c = a-b = 32769! 
雪山飞狐D 2021-1-19 19:13 回复TA
@791314247 :那就通通用有符号类型就好了,只要数据不超过有符号范围,实在超过,就只能自定义64位运算了 
791314247 2021-1-19 18:38 回复TA
这样是可以的,但可惜编译器最大是32位的 
14
fcccc| | 2021-1-19 19:10 | 只看该作者
在嵌入式软件设计中,变量的声明应该坚最小类型原则;
因为对于一个8位或者32位MCU处理int64_t类型的计算需要花费更多时钟周期;
因为寄存器的位宽有限,需要分几次加载长度超过位宽的变量.
如果能确定short类型能放得下,就不要用int;我用short类型举例也是这个意思;

使用特权

评论回复
15
ayb_ice| | 2021-1-20 11:32 | 只看该作者
这种情况本身就是可能产生情况,结果溢出,符号位发生变化,这是程序员本身应该考虑的事

使用特权

评论回复
16
xjl85| | 2021-1-22 10:07 | 只看该作者
这不就是个类型转换问题嘛

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

22

帖子

0

粉丝