为啥 MISRA-C 在某些情况下不允许隐式扩展类型?

Posted

技术标签:

【中文标题】为啥 MISRA-C 在某些情况下不允许隐式扩展类型?【英文标题】:Why MISRA-C disallow implicitly widening a type in some circumstances?为什么 MISRA-C 在某些情况下不允许隐式扩展类型? 【发布时间】:2019-03-23 00:47:05 【问题描述】: MISRA-C:2004 规则 10.1 不允许隐式扩展 函数参数返回表达式 的类型,如以下代码sn -p:
void foo1(int16_t x);

int16_t foo2(void) 

    int8_t s8a;
    ...
    foo1(s8a);                               /* not compliant */
    ...
    return s8a;                              /* not compliant */

但是,据我了解,它们与分配情况没有什么不同:

s16a = s8a;                                  /* compliant     */

有什么意义?谢谢。

【问题讨论】:

Rust 也有类似的限制,您需要显式强制转换(例如 let a: u16 = 3u8 as u16)。有很多关于这个的讨论,例如internals.rust-lang.org/t/… 。我还没有完整地阅读这个,但总结是,你不会在不知不觉中将不同的类型添加在一起,例如一个 u16 和一个 u8,因为结果可能令人惊讶。 我猜是 Misra-C:2004 规则 10.1The value of an expression of integer type shall not be implicitly converted to a different underlying type if: [..] the expression is not constant and is a function argument [...] 。但下面写的是它们的意思是不允许从更宽类型到更窄类型的转换,反之亦然。 您能否引用您所指的 MISRA C 规则,@dingcure ? @Andrew 正如 Kamil Cuk 所指出的,这是 MISRA-C:2004 规则 10.1。 【参考方案1】:

MISRA-C:2004 规则 10.1(引用的指南)规定:

整数类型表达式的值不应隐含 在以下情况下转换为不同的基础类型:

    它不是转换为具有相同符号的更广泛的整数类型,或者 ...

在引用的示例中,转换到更宽的整数类型(int8_t 到 int16_t),因此规则 10.1 不适用。

(10.1 和 10.2 的)扩展说明该规则的目的是防止从较宽类型到较窄类型的隐式转换。反之则无限制!

你的工具坏了。

【讨论】:

但是 OP 的示例取自规则 10.1(尽管在一种情况下被错误地复制)。我的回答和你一样,但问题是“d)表达式不是常量,是一个返回表达式”。为什么 MISRA-C:2004 有这个奇怪的规则,我无法回答——因为它没有任何意义。返回值和传递的参数是左值转换。将左值转换为具有相同符号的更广泛的整数类型是非常安全的。 MISRA-C:2012 幸运的是没有这个奇怪的规则。我不知道委员会在 2004 年对 10.1 c) 和 d) 有什么想法。 也就是说,文本“不合规”不是来自损坏的工具,而是来自 MISRA-C:2004 规则 10.1 下面的示例。

以上是关于为啥 MISRA-C 在某些情况下不允许隐式扩展类型?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 AppDomain.CurrentDomain.GetAssemblies() 在某些情况下不返回 Global.asax 中的依赖程序集?

为啥 PHP 在一种情况下允许将文字传递给按引用传递的参数,而在其他情况下不允许?

jquery 数据表头在某些情况下不扩展或扩展缓慢,例如重新加载

为啥仅在某些情况下才能将字符串文字隐式转换为 char* ? [复制]

为啥 Java 中的每个对象都隐式扩展 java.lang.Object 类?

为啥 MISRA-C 检查器提供错误检查 STM32 HAL?