【问题标题】:MISRA C 2004 10.1, signedness of printf "%x"MISRA C 2004 10.1,printf "%x" 的签名
【发布时间】:2015-04-27 23:59:12
【问题描述】:

我从我们的静态分析工具中收到关于以下 sn-p 的错误:

uint8_t value = 24U;
char buffer[512];
int chars_printed = snprintf(buffer, sizeof(buffer),
                             "The value in hex is 0x%02hhX\r\n",
                             value);

错误是:

MISRA-2004 违反规则 10.1:隐式转换函数参数中的非常量表达式。将底层类型为“unsigned char”(8 位,无符号)的“值”转换为类型“int”(32 位,有符号)。

MISRA 期望“%X”说明符的符号和位宽是多少?

据说“%X”从cppreference page 中获取unsigned int

IAR 编译器的 MISRA C 2004 检查器没有错误。
这个来自 Coverity。

【问题讨论】:

  • snprintf 采用可变参数列表,因此 value 将进行整体提升。您应该可以通过投射 (unsigned)value 来消除警告
  • @Praetorian,这并不能解释签名问题。我可以将相同的签名提升到更大的类型,但是这个“int32_t”类型来自哪里?它是可变参数列表吗?我在任何 C 语言资源中都没有看到任何参数定义。
  • 如果你在可变参数列表中传递一个小于int的类型,它会被提升为int。阅读默认转化部分here
  • 你有那个来源的链接吗,pdf?
  • stackoverflow.com/q/1255775/995714 比 int 窄的类型将被提升为 int

标签: c printf type-conversion format-specifiers misra


【解决方案1】:

问题在于 printf 系列隐式地将所有小整数类型的参数提升为int。规则 10.1 不允许此类隐式类型提升,这就是您收到 MISRA 违规错误的原因。它与格式说明符无关。

为了符合 MISRA,只需在将值传递给函数之前显式转换值:(uint32_t)value

另请注意,MISRA 不允许您在生产代码中使用 stdio.h。

【讨论】:

  • 顺便说一句,在这种情况下,Coverity 似乎比 IAR 做得更好。
  • 实际上,只要记录了差异,MISRA 确实允许使用。我们正在使用字符串 printf 和 scanf 函数;因为我们不想自己编写和测试。
  • @ThomasMatthews 记录 stdio.h 函数附带的所有指定不当的行为和所有其他陷阱似乎是一项艰巨的任务……您必须写一本书。这是一个很好的规则,在关键任务系统的生产代码中使用这些函数是非常值得怀疑的做法。至于 sprintf/sscanf,推出您自己的版本只需不到一小时的工作时间,因为您只使用它们来转换整数(而不是浮点数等)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-29
  • 1970-01-01
  • 2012-02-26
  • 1970-01-01
  • 1970-01-01
  • 2015-12-09
  • 1970-01-01
相关资源
最近更新 更多